@linktic/validator 1.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 +177 -0
- package/dist/chunk-5LU5LI4H.js +44 -0
- package/dist/chunk-GGX2GQQ6.cjs +47 -0
- package/dist/es-QPgrpTLv.d.cts +22 -0
- package/dist/es-QPgrpTLv.d.ts +22 -0
- package/dist/index.cjs +454 -0
- package/dist/index.d.cts +159 -0
- package/dist/index.d.ts +159 -0
- package/dist/index.js +437 -0
- package/dist/messages/es.cjs +10 -0
- package/dist/messages/es.d.cts +1 -0
- package/dist/messages/es.d.ts +1 -0
- package/dist/messages/es.js +1 -0
- package/package.json +62 -0
package/README.md
ADDED
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
# @linktic/validator
|
|
2
|
+
|
|
3
|
+
Libreria de validacion TypeScript con API fluida, zero dependencias y mensajes en espanol configurables.
|
|
4
|
+
|
|
5
|
+
## Instalacion
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
# pnpm
|
|
9
|
+
pnpm add @linktic/validator
|
|
10
|
+
|
|
11
|
+
# npm
|
|
12
|
+
npm install @linktic/validator
|
|
13
|
+
|
|
14
|
+
# yarn
|
|
15
|
+
yarn add @linktic/validator
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
## Uso basico
|
|
19
|
+
|
|
20
|
+
```typescript
|
|
21
|
+
import { validate, ValidationError } from '@linktic/validator'
|
|
22
|
+
|
|
23
|
+
const data = { name: '', email: 'bad', age: 15 }
|
|
24
|
+
const v = validate(data)
|
|
25
|
+
|
|
26
|
+
v.field('name', 'Nombre').required().string()
|
|
27
|
+
v.field('email', 'Correo').required().email()
|
|
28
|
+
v.field('age', 'Edad').required().number().min(18)
|
|
29
|
+
|
|
30
|
+
// Opcion A: lanzar error
|
|
31
|
+
try {
|
|
32
|
+
v.validate()
|
|
33
|
+
} catch (e) {
|
|
34
|
+
if (e instanceof ValidationError) {
|
|
35
|
+
console.log(e.errors) // ValidationFieldError[]
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
// Opcion B: inspeccionar resultado
|
|
40
|
+
const result = v.getResult()
|
|
41
|
+
if (!result.isValid) {
|
|
42
|
+
console.log(result.errors)
|
|
43
|
+
}
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
## Validacion por schema
|
|
47
|
+
|
|
48
|
+
```typescript
|
|
49
|
+
const v = validate(data)
|
|
50
|
+
|
|
51
|
+
v.schema({
|
|
52
|
+
name: { required: true, type: 'string', label: 'Nombre', minLength: 2, maxLength: 100 },
|
|
53
|
+
email: { required: true, type: 'email', label: 'Correo' },
|
|
54
|
+
age: { required: true, type: 'number', label: 'Edad', min: 18, max: 120 },
|
|
55
|
+
role: { required: true, label: 'Rol', enum: ['admin', 'user', 'viewer'] },
|
|
56
|
+
notes: { required: false, type: 'string', label: 'Notas', maxLength: 500 },
|
|
57
|
+
})
|
|
58
|
+
|
|
59
|
+
v.validate()
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
## Campos anidados
|
|
63
|
+
|
|
64
|
+
```typescript
|
|
65
|
+
const v = validate({ office: { name: 'HQ', classId: '001' } })
|
|
66
|
+
|
|
67
|
+
v.field('office.name', 'Nombre oficina').required().string()
|
|
68
|
+
v.field('office.classId', 'Clase de oficina').required().string()
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
## Validadores personalizados
|
|
72
|
+
|
|
73
|
+
```typescript
|
|
74
|
+
v.field('username', 'Usuario').custom((value) => {
|
|
75
|
+
if ((value as string).includes(' ')) return 'No puede contener espacios'
|
|
76
|
+
return true
|
|
77
|
+
})
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
## Configuracion de mensajes
|
|
81
|
+
|
|
82
|
+
Por defecto los mensajes vienen en espanol. Puedes personalizarlos:
|
|
83
|
+
|
|
84
|
+
### Sobrescribir mensajes especificos
|
|
85
|
+
|
|
86
|
+
```typescript
|
|
87
|
+
import { configure } from '@linktic/validator'
|
|
88
|
+
|
|
89
|
+
configure({
|
|
90
|
+
required: (field) => `${field} is required`,
|
|
91
|
+
email: () => 'Please enter a valid email',
|
|
92
|
+
})
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
### Reemplazar todos los mensajes (cambio de idioma)
|
|
96
|
+
|
|
97
|
+
```typescript
|
|
98
|
+
import { setMessages, spanishMessages } from '@linktic/validator'
|
|
99
|
+
import type { ValidationMessageMap } from '@linktic/validator'
|
|
100
|
+
|
|
101
|
+
const english: ValidationMessageMap = {
|
|
102
|
+
required: (field) => `${field} is required. Please fill it in.`,
|
|
103
|
+
pattern: (field, example) => `${field} format is invalid. Expected: ${example}`,
|
|
104
|
+
maxLength: (field, max, actual) => `${field} exceeds ${max} characters (${actual} entered).`,
|
|
105
|
+
minLength: (field, min) => `${field} requires at least ${min} characters.`,
|
|
106
|
+
range: (field, min, max) => `${field} must be between ${min} and ${max}.`,
|
|
107
|
+
date: (field) => `${field} is not a valid date.`,
|
|
108
|
+
allowedChars: (field, allowed) => `${field} contains invalid characters. Only: ${allowed}`,
|
|
109
|
+
email: () => 'The email entered is not valid',
|
|
110
|
+
string: (field) => `${field} must be text`,
|
|
111
|
+
number: (field) => `${field} must be a number`,
|
|
112
|
+
boolean: (field) => `${field} must be true or false`,
|
|
113
|
+
array: (field) => `${field} must be a list`,
|
|
114
|
+
object: (field) => `${field} must be an object`,
|
|
115
|
+
uuid: (field) => `${field} must be a valid identifier`,
|
|
116
|
+
enum: (field, values) => `${field} must be one of: ${values.join(', ')}`,
|
|
117
|
+
custom: (field) => `${field} is not valid`,
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
setMessages(english)
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
### Restaurar mensajes por defecto
|
|
124
|
+
|
|
125
|
+
```typescript
|
|
126
|
+
import { resetMessages } from '@linktic/validator'
|
|
127
|
+
|
|
128
|
+
resetMessages() // Vuelve a espanol
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
## API de FieldValidator
|
|
132
|
+
|
|
133
|
+
| Metodo | Descripcion |
|
|
134
|
+
|--------|-------------|
|
|
135
|
+
| `required(msg?)` | Campo obligatorio |
|
|
136
|
+
| `optional()` | Campo opcional (salta validaciones si esta vacio) |
|
|
137
|
+
| `nullable()` | Alias de `optional()` |
|
|
138
|
+
| `string(msg?)` | Debe ser string |
|
|
139
|
+
| `number(msg?)` | Debe ser number |
|
|
140
|
+
| `boolean(msg?)` | Debe ser boolean |
|
|
141
|
+
| `array(msg?)` | Debe ser array |
|
|
142
|
+
| `object(msg?)` | Debe ser objeto (no array) |
|
|
143
|
+
| `date(msg?)` | Debe ser fecha valida |
|
|
144
|
+
| `email(msg?)` | Debe ser email valido |
|
|
145
|
+
| `uuid(msg?)` | Debe ser UUID valido |
|
|
146
|
+
| `type(type, msg?)` | Validar por tipo (`ValidationType`) |
|
|
147
|
+
| `minLength(min, msg?)` | Longitud minima (string/array) |
|
|
148
|
+
| `maxLength(max, msg?)` | Longitud maxima (string/array) |
|
|
149
|
+
| `min(value, msg?)` | Valor minimo (number) |
|
|
150
|
+
| `max(value, msg?)` | Valor maximo (number) |
|
|
151
|
+
| `range(min, max, msg?)` | Rango numerico |
|
|
152
|
+
| `pattern(regex, example?, msg?)` | Validar contra regex |
|
|
153
|
+
| `enum(values, msg?)` | Debe ser uno de los valores |
|
|
154
|
+
| `allowedChars(chars, msg?)` | Solo caracteres permitidos |
|
|
155
|
+
| `custom(fn, msg?)` | Validador personalizado |
|
|
156
|
+
|
|
157
|
+
## API de Validator
|
|
158
|
+
|
|
159
|
+
| Metodo | Descripcion |
|
|
160
|
+
|--------|-------------|
|
|
161
|
+
| `field(name, label?)` | Iniciar validacion de un campo |
|
|
162
|
+
| `schema(config)` | Validar con configuracion de schema |
|
|
163
|
+
| `validate()` | Lanzar `ValidationError` si hay errores |
|
|
164
|
+
| `getResult()` | Obtener `{ isValid, errors }` |
|
|
165
|
+
| `getErrors()` | Obtener array de errores |
|
|
166
|
+
| `isValid()` | `true` si no hay errores |
|
|
167
|
+
| `hasErrors()` | `true` si hay errores |
|
|
168
|
+
| `reset()` | Limpiar errores |
|
|
169
|
+
|
|
170
|
+
## Opciones
|
|
171
|
+
|
|
172
|
+
```typescript
|
|
173
|
+
const v = validate(data, {
|
|
174
|
+
stopOnFirstError: true, // Detener en el primer error por campo
|
|
175
|
+
throwOnError: true, // Lanzar inmediatamente al encontrar error (con stopOnFirstError)
|
|
176
|
+
})
|
|
177
|
+
```
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
// src/utils.ts
|
|
2
|
+
function interpolate(template, params) {
|
|
3
|
+
return template.replace(
|
|
4
|
+
/\{(\w+)\}/g,
|
|
5
|
+
(_, key) => String(params[key] ?? "")
|
|
6
|
+
);
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
// src/messages/es.ts
|
|
10
|
+
var spanishMessages = {
|
|
11
|
+
required: (campo) => interpolate(
|
|
12
|
+
"El campo {campo} es obligatorio. Por favor compl\xE9talo para continuar.",
|
|
13
|
+
{ campo }
|
|
14
|
+
),
|
|
15
|
+
pattern: (campo, ejemplo) => interpolate(
|
|
16
|
+
"El formato de {campo} no es v\xE1lido. Ejemplo esperado: {ejemplo}",
|
|
17
|
+
{ campo, ejemplo }
|
|
18
|
+
),
|
|
19
|
+
maxLength: (campo, max, actual) => interpolate(
|
|
20
|
+
"{campo} excede el l\xEDmite de {max} caracteres ({actual} ingresados).",
|
|
21
|
+
{ campo, max, actual }
|
|
22
|
+
),
|
|
23
|
+
minLength: (campo, min) => interpolate("{campo} requiere m\xEDnimo {min} caracteres.", { campo, min }),
|
|
24
|
+
range: (campo, min, max) => interpolate("{campo} debe estar entre {min} y {max}.", { campo, min, max }),
|
|
25
|
+
date: (campo) => interpolate(
|
|
26
|
+
"La fecha en {campo} no es v\xE1lida. Formato esperado: DD/MM/AAAA",
|
|
27
|
+
{ campo }
|
|
28
|
+
),
|
|
29
|
+
allowedChars: (campo, permitidos) => interpolate(
|
|
30
|
+
"{campo} contiene caracteres no permitidos. Solo se aceptan: {permitidos}",
|
|
31
|
+
{ campo, permitidos }
|
|
32
|
+
),
|
|
33
|
+
email: () => "El correo ingresado no es valido",
|
|
34
|
+
string: (campo) => `${campo} debe ser texto`,
|
|
35
|
+
number: (campo) => `${campo} debe ser un n\xFAmero`,
|
|
36
|
+
boolean: (campo) => `${campo} debe ser verdadero o falso`,
|
|
37
|
+
array: (campo) => `${campo} debe ser una lista`,
|
|
38
|
+
object: (campo) => `${campo} debe ser un objeto`,
|
|
39
|
+
uuid: (campo) => `${campo} debe ser un identificador v\xE1lido`,
|
|
40
|
+
enum: (campo, valores) => `${campo} debe ser uno de: ${valores.join(", ")}`,
|
|
41
|
+
custom: (campo) => `${campo} no es v\xE1lido`
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
export { interpolate, spanishMessages };
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
// src/utils.ts
|
|
4
|
+
function interpolate(template, params) {
|
|
5
|
+
return template.replace(
|
|
6
|
+
/\{(\w+)\}/g,
|
|
7
|
+
(_, key) => String(params[key] ?? "")
|
|
8
|
+
);
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
// src/messages/es.ts
|
|
12
|
+
var spanishMessages = {
|
|
13
|
+
required: (campo) => interpolate(
|
|
14
|
+
"El campo {campo} es obligatorio. Por favor compl\xE9talo para continuar.",
|
|
15
|
+
{ campo }
|
|
16
|
+
),
|
|
17
|
+
pattern: (campo, ejemplo) => interpolate(
|
|
18
|
+
"El formato de {campo} no es v\xE1lido. Ejemplo esperado: {ejemplo}",
|
|
19
|
+
{ campo, ejemplo }
|
|
20
|
+
),
|
|
21
|
+
maxLength: (campo, max, actual) => interpolate(
|
|
22
|
+
"{campo} excede el l\xEDmite de {max} caracteres ({actual} ingresados).",
|
|
23
|
+
{ campo, max, actual }
|
|
24
|
+
),
|
|
25
|
+
minLength: (campo, min) => interpolate("{campo} requiere m\xEDnimo {min} caracteres.", { campo, min }),
|
|
26
|
+
range: (campo, min, max) => interpolate("{campo} debe estar entre {min} y {max}.", { campo, min, max }),
|
|
27
|
+
date: (campo) => interpolate(
|
|
28
|
+
"La fecha en {campo} no es v\xE1lida. Formato esperado: DD/MM/AAAA",
|
|
29
|
+
{ campo }
|
|
30
|
+
),
|
|
31
|
+
allowedChars: (campo, permitidos) => interpolate(
|
|
32
|
+
"{campo} contiene caracteres no permitidos. Solo se aceptan: {permitidos}",
|
|
33
|
+
{ campo, permitidos }
|
|
34
|
+
),
|
|
35
|
+
email: () => "El correo ingresado no es valido",
|
|
36
|
+
string: (campo) => `${campo} debe ser texto`,
|
|
37
|
+
number: (campo) => `${campo} debe ser un n\xFAmero`,
|
|
38
|
+
boolean: (campo) => `${campo} debe ser verdadero o falso`,
|
|
39
|
+
array: (campo) => `${campo} debe ser una lista`,
|
|
40
|
+
object: (campo) => `${campo} debe ser un objeto`,
|
|
41
|
+
uuid: (campo) => `${campo} debe ser un identificador v\xE1lido`,
|
|
42
|
+
enum: (campo, valores) => `${campo} debe ser uno de: ${valores.join(", ")}`,
|
|
43
|
+
custom: (campo) => `${campo} no es v\xE1lido`
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
exports.interpolate = interpolate;
|
|
47
|
+
exports.spanishMessages = spanishMessages;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
interface ValidationMessageMap {
|
|
2
|
+
required: (campo: string) => string;
|
|
3
|
+
pattern: (campo: string, ejemplo: string) => string;
|
|
4
|
+
maxLength: (campo: string, max: number, actual: number) => string;
|
|
5
|
+
minLength: (campo: string, min: number) => string;
|
|
6
|
+
range: (campo: string, min: number, max: number) => string;
|
|
7
|
+
date: (campo: string) => string;
|
|
8
|
+
allowedChars: (campo: string, permitidos: string) => string;
|
|
9
|
+
email: () => string;
|
|
10
|
+
string: (campo: string) => string;
|
|
11
|
+
number: (campo: string) => string;
|
|
12
|
+
boolean: (campo: string) => string;
|
|
13
|
+
array: (campo: string) => string;
|
|
14
|
+
object: (campo: string) => string;
|
|
15
|
+
uuid: (campo: string) => string;
|
|
16
|
+
enum: (campo: string, valores: unknown[]) => string;
|
|
17
|
+
custom: (campo: string) => string;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
declare const spanishMessages: ValidationMessageMap;
|
|
21
|
+
|
|
22
|
+
export { type ValidationMessageMap as V, spanishMessages as s };
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
interface ValidationMessageMap {
|
|
2
|
+
required: (campo: string) => string;
|
|
3
|
+
pattern: (campo: string, ejemplo: string) => string;
|
|
4
|
+
maxLength: (campo: string, max: number, actual: number) => string;
|
|
5
|
+
minLength: (campo: string, min: number) => string;
|
|
6
|
+
range: (campo: string, min: number, max: number) => string;
|
|
7
|
+
date: (campo: string) => string;
|
|
8
|
+
allowedChars: (campo: string, permitidos: string) => string;
|
|
9
|
+
email: () => string;
|
|
10
|
+
string: (campo: string) => string;
|
|
11
|
+
number: (campo: string) => string;
|
|
12
|
+
boolean: (campo: string) => string;
|
|
13
|
+
array: (campo: string) => string;
|
|
14
|
+
object: (campo: string) => string;
|
|
15
|
+
uuid: (campo: string) => string;
|
|
16
|
+
enum: (campo: string, valores: unknown[]) => string;
|
|
17
|
+
custom: (campo: string) => string;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
declare const spanishMessages: ValidationMessageMap;
|
|
21
|
+
|
|
22
|
+
export { type ValidationMessageMap as V, spanishMessages as s };
|