structure-verifier 0.0.17 → 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.
Files changed (2) hide show
  1. package/README.md +232 -329
  2. package/package.json +1 -1
package/README.md CHANGED
@@ -2,32 +2,33 @@
2
2
 
3
3
  Libreria de validacion para TypeScript orientada a esquemas declarativos, tipado inferido y errores detallados por ruta.
4
4
 
5
- Ideal para validar payloads de API, formularios, configuraciones y estructuras anidadas complejas.
6
-
7
- Version actual: 0.0.17
8
-
9
- ## Contenido
10
-
11
- - Caracteristicas
12
- - Instalacion
13
- - Inicio rapido
14
- - Conceptos base
15
- - API publica
16
- - Referencia completa de validadores
17
- - Transformaciones de valores
18
- - Tipado inferido
19
- - Manejo de errores
20
- - Ejemplos avanzados
21
- - Scripts de desarrollo
22
-
23
- ## Caracteristicas
24
-
25
- - Validadores para number, string, boolean, uuid, date, array, object y any.
26
- - Soporte para estructuras anidadas con errores por ruta.
27
- - API fluida por clases y API de fabrica mediante Verifiers.
28
- - Tipado inferido en compile-time para mantener consistencia del dominio.
29
- - Personalizacion de mensajes por regla y por validador.
30
- - Integracion con dayjs (exportado como datetime) para manejo de fechas.
5
+ Ideal para validar payloads de API, formularios, configuraciones y estructuras anidadas.
6
+
7
+ ## Objetivo de esta documentacion
8
+
9
+ Este README está diseñado para ayudarte a:
10
+
11
+ - Comprender rápidamente cómo funciona la librería.
12
+ - Integrarla de forma sencilla en un proyecto real.
13
+ - Conocer el contrato público de la API antes de utilizarla en producción.
14
+ - Explorar ejemplos prácticos de validación y tipado.
15
+ - Entender las decisiones de diseño y el enfoque de la librería.
16
+
17
+ ## Tabla de contenido
18
+
19
+ - [Instalacion](#instalacion)
20
+ - [Inicio rapido](#inicio-rapido)
21
+ - [Conceptos clave](#conceptos-clave)
22
+ - [API publica](#api-publica)
23
+ - [Estilos de uso](#estilos-de-uso)
24
+ - [Validadores disponibles](#validadores-disponibles)
25
+ - [Transformaciones](#transformaciones)
26
+ - [Tipado inferido](#tipado-inferido)
27
+ - [Manejo de errores](#manejo-de-errores)
28
+ - [datetime (dayjs)](#datetime-dayjs)
29
+ - [Buenas practicas para v1.0.0](#buenas-practicas-para-v100)
30
+ - [Scripts de desarrollo](#scripts-de-desarrollo)
31
+ - [Licencia](#licencia)
31
32
 
32
33
  ## Instalacion
33
34
 
@@ -42,11 +43,11 @@ import { Verifiers as V, VerificationError } from "structure-verifier";
42
43
 
43
44
  const userVerifier = V.ObjectNotNull(
44
45
  {
45
- id: V.UUIDNotNull({ version: 4 }),
46
- name: V.StringNotNull({ minLength: 2 }),
46
+ id: V.UUID({ version: 4 }).required(),
47
+ name: V.StringNotNull({ minLength: 2 }).trim(),
47
48
  age: V.Number({ min: 0 }),
48
49
  active: V.BooleanNotNull(),
49
- tags: V.ArrayNotNull(V.StringNotNull()).minLength(1),
50
+ tags: V.ArrayNotNull(V.StringNotNull(), { minLength: 1 }),
50
51
  },
51
52
  {
52
53
  strictMode: true,
@@ -56,48 +57,64 @@ const userVerifier = V.ObjectNotNull(
56
57
  try {
57
58
  const user = userVerifier.check({
58
59
  id: "550e8400-e29b-41d4-a716-446655440000",
59
- name: "Ana",
60
+ name: " Ana ",
60
61
  age: "31",
61
62
  active: "true",
62
63
  tags: ["admin"],
63
64
  });
64
65
 
65
66
  console.log(user);
67
+ // {
68
+ // id: "550e8400-e29b-41d4-a716-446655440000",
69
+ // name: "Ana",
70
+ // age: 31,
71
+ // active: true,
72
+ // tags: ["admin"]
73
+ // }
66
74
  } catch (error) {
67
75
  if (error instanceof VerificationError) {
68
- console.log(error.message);
69
- console.log(error.errors);
70
- console.log(error.errorsObj);
76
+ console.error(error.message);
77
+ console.error(error.errors);
78
+ console.error(error.errorsObj);
71
79
  }
72
80
  }
73
81
  ```
74
82
 
75
- ## Conceptos base
83
+ ## Conceptos clave
76
84
 
77
85
  ### 1) Nullable vs NotNull
78
86
 
79
- - VNumber, VString, VBoolean, VDate, VUUID, VArray y VObject retornan tipo nullable.
80
- - Sus versiones NotNull retornan el tipo requerido.
81
- - Tambien puedes promover un validador nullable a requerido con required().
87
+ - `VNumber`, `VString`, `VBoolean`, `VDate`, `VUUID`, `VArray`, `VObject` y `VAny` pueden devolver `null`.
88
+ - Las variantes `NotNull` devuelven siempre tipo requerido.
89
+ - En validadores nullable puedes promover a requerido con `.required()`.
82
90
 
83
- ### 2) Reglas comunes
91
+ ### 2) Inmutabilidad de reglas
84
92
 
85
- Muchos validadores comparten estas opciones:
93
+ Cada metodo de regla devuelve una nueva instancia del validador.
94
+
95
+ ```ts
96
+ const base = V.StringNotNull();
97
+ const withMin = base.minLength(3);
98
+
99
+ // base no cambia
100
+ ```
101
+
102
+ ### 3) Reglas transversales
86
103
 
87
- - isRequired: fuerza que el valor exista.
88
- - emptyAsNull: transforma string vacio a null antes de validar.
89
- - defaultValue: valor por defecto para undefined y, en algunos casos, null.
90
- - badTypeMessage: reemplaza el mensaje de tipo invalido.
104
+ Muchos validadores comparten estas opciones:
91
105
 
92
- ### 3) Mensajes personalizados
106
+ - `isRequired`: fuerza existencia del valor.
107
+ - `emptyAsNull`: transforma `""` a `null` antes de validar.
108
+ - `defaultValue`: valor por defecto para `undefined` y ciertos casos de `null`.
109
+ - `badTypeMessage`: reemplaza mensaje de tipo invalido.
93
110
 
94
- Las reglas aceptan mensajes de estas formas:
111
+ ### 4) Mensajes personalizados
95
112
 
96
- - String fijo.
97
- - Funcion callback con el objeto de valores de la regla.
98
- - Objeto con estructura val + message.
113
+ Puedes pasar mensajes como:
99
114
 
100
- Ejemplo:
115
+ - `string` fijo.
116
+ - callback usando el valor de la regla.
117
+ - objeto `{ val, message }`.
101
118
 
102
119
  ```ts
103
120
  const age = V.NumberNotNull().min(18, (v) => `Edad minima: ${v.min}`);
@@ -105,7 +122,13 @@ const age = V.NumberNotNull().min(18, (v) => `Edad minima: ${v.min}`);
105
122
 
106
123
  ## API publica
107
124
 
108
- Import principal:
125
+ Import principal recomendado:
126
+
127
+ ```ts
128
+ import { Verifiers as V } from "structure-verifier";
129
+ ```
130
+
131
+ Import completo disponible:
109
132
 
110
133
  ```ts
111
134
  import {
@@ -133,17 +156,17 @@ import {
133
156
  } from "structure-verifier";
134
157
  ```
135
158
 
136
- Tambien se exportan los tipos de condiciones:
159
+ Tambien se exportan estos tipos de condiciones:
137
160
 
138
- - VAnyConditions
139
- - VArrayConditions
140
- - VBooleanConditions
141
- - VDateConditions
142
- - VNumberConditions
143
- - VObjectConditions
144
- - VObjectConditionsNotNull
145
- - VStringConditions
146
- - VUUIDConditions
161
+ - `VAnyConditions`
162
+ - `VArrayConditions`
163
+ - `VBooleanConditions`
164
+ - `VDateConditions`
165
+ - `VNumberConditions`
166
+ - `VObjectConditions`
167
+ - `VObjectConditionsNotNull`
168
+ - `VStringConditions`
169
+ - `VUUIDConditions`
147
170
 
148
171
  ## Estilos de uso
149
172
 
@@ -163,281 +186,186 @@ import { VStringNotNull } from "structure-verifier";
163
186
  const nameV = new VStringNotNull({ minLength: 3 });
164
187
  ```
165
188
 
166
- ### Callable constructors
189
+ ### Callable constructors en `Verifiers`
167
190
 
168
- En Verifiers puedes usar los miembros como funcion o con new.
191
+ Los miembros de `Verifiers` aceptan llamada normal o `new`.
169
192
 
170
193
  ```ts
171
194
  const a = V.NumberNotNull({ min: 1 });
172
195
  const b = new V.NumberNotNull({ min: 1 });
173
196
  ```
174
197
 
175
- ## Referencia completa de validadores
176
-
177
- ### Number y NumberNotNull
178
-
179
- Retorno:
180
-
181
- - VNumber: number | null
182
- - VNumberNotNull: number
183
-
184
- Condiciones:
185
-
186
- - min
187
- - max
188
- - in
189
- - notIn
190
- - maxDecimalPlaces
191
- - minDecimalPlaces
192
- - isRequired
193
- - emptyAsNull
194
- - defaultValue
195
- - badTypeMessage
196
-
197
- Comportamiento clave:
198
-
199
- - Convierte el valor usando Number(data).
200
- - Rechaza string vacio y NaN.
201
-
202
- Ejemplo:
203
-
204
- ```ts
205
- const priceV = V.NumberNotNull().min(0).maxDecimalPlaces(2);
206
- const price = priceV.check("25.99");
207
- ```
208
-
209
- ### String y StringNotNull
210
-
211
- Retorno:
198
+ ## Validadores disponibles
212
199
 
213
- - VString: string | null
214
- - VStringNotNull: string
200
+ ### Number / NumberNotNull
215
201
 
216
- Condiciones:
202
+ Salida:
217
203
 
218
- - minLength
219
- - maxLength
220
- - regex
221
- - notRegex
222
- - in
223
- - notIn
224
- - strictMode
225
- - ignoreCase
226
- - isRequired
227
- - emptyAsNull
228
- - defaultValue
229
- - badTypeMessage
204
+ - `VNumber`: `number | null`
205
+ - `VNumberNotNull`: `number`
230
206
 
231
- Comportamiento clave:
207
+ Reglas:
232
208
 
233
- - En modo normal convierte con String(data).
234
- - En strictMode exige string real.
235
- - ignoreCase afecta in y notIn.
209
+ - `min`
210
+ - `max`
211
+ - `in`
212
+ - `notIn`
213
+ - `maxDecimalPlaces`
214
+ - `minDecimalPlaces`
215
+ - reglas transversales (`isRequired`, `emptyAsNull`, `defaultValue`, `badTypeMessage`)
236
216
 
237
- Ejemplo:
238
-
239
- ```ts
240
- const roleV = V.StringNotNull()
241
- .ignoreCase()
242
- .in(["admin", "user", "guest"])
243
- .trim()
244
- .toLowerCase();
217
+ Comportamiento importante:
245
218
 
246
- const role = roleV.check(" ADMIN ");
247
- ```
219
+ - Convierte con `Number(data)`.
220
+ - Rechaza `""` y valores `NaN`.
248
221
 
249
- ### Boolean y BooleanNotNull
222
+ ### String / StringNotNull
250
223
 
251
- Retorno:
224
+ Salida:
252
225
 
253
- - VBoolean: boolean | null
254
- - VBooleanNotNull: boolean
226
+ - `VString`: `string | null`
227
+ - `VStringNotNull`: `string`
255
228
 
256
- Condiciones:
229
+ Reglas:
257
230
 
258
- - strictMode
259
- - isRequired
260
- - emptyAsNull
261
- - defaultValue
262
- - badTypeMessage
231
+ - `minLength`
232
+ - `maxLength`
233
+ - `regex`
234
+ - `notRegex`
235
+ - `in`
236
+ - `notIn`
237
+ - `strictMode`
238
+ - `ignoreCase`
239
+ - reglas transversales
263
240
 
264
- Comportamiento clave:
241
+ Comportamiento importante:
265
242
 
266
- - En modo normal acepta: true, false, 1, 0, "1", "0", "true", "false".
267
- - En strictMode solo acepta boolean.
243
+ - En modo normal convierte con `String(data)`.
244
+ - En `strictMode` exige tipo string real.
245
+ - `ignoreCase` aplica a reglas `in` y `notIn`.
268
246
 
269
- Ejemplo:
247
+ ### Boolean / BooleanNotNull
270
248
 
271
- ```ts
272
- const active = V.BooleanNotNull().check("true");
273
- const strictActive = V.BooleanNotNull().strictMode().check(true);
274
- ```
249
+ Salida:
275
250
 
276
- ### UUID y UUIDNotNull
251
+ - `VBoolean`: `boolean | null`
252
+ - `VBooleanNotNull`: `boolean`
277
253
 
278
- Retorno:
254
+ Reglas:
279
255
 
280
- - VUUID: string | null
281
- - VUUIDNotNull: string
256
+ - `strictMode`
257
+ - reglas transversales
282
258
 
283
- Condiciones:
259
+ Comportamiento importante:
284
260
 
285
- - version (1 | 2 | 3 | 4 | 5)
286
- - allowNoHyphens
287
- - strictMode
288
- - isRequired
289
- - emptyAsNull
290
- - defaultValue
291
- - badTypeMessage
261
+ - Modo normal acepta: `true`, `false`, `1`, `0`, `"1"`, `"0"`, `"true"`, `"false"`.
262
+ - `strictMode` acepta solo boolean real.
292
263
 
293
- Comportamiento clave:
264
+ ### UUID / UUIDNotNull
294
265
 
295
- - Normaliza salida a minusculas y formato con guiones.
296
- - Si allowNoHyphens no esta activo, exige formato 8-4-4-4-12.
266
+ Salida:
297
267
 
298
- Ejemplo:
268
+ - `VUUID`: `string | null`
269
+ - `VUUIDNotNull`: `string`
299
270
 
300
- ```ts
301
- const uuidV = V.UUIDNotNull().version(4);
302
- const id = uuidV.check("550E8400E29B41D4A716446655440000");
303
- ```
271
+ Reglas:
304
272
 
305
- ### Date y DateNotNull
273
+ - `version` (`1 | 2 | 3 | 4 | 5`)
274
+ - `allowNoHyphens`
275
+ - `strictMode`
276
+ - reglas transversales
306
277
 
307
- Retorno:
278
+ Comportamiento importante:
308
279
 
309
- - VDate: datetime.Dayjs | null
310
- - VDateNotNull: datetime.Dayjs
280
+ - Normaliza salida a minusculas con formato `8-4-4-4-12`.
281
+ - Si `allowNoHyphens` es `false`, exige UUID con guiones.
311
282
 
312
- Condiciones:
283
+ ### Date / DateNotNull
313
284
 
314
- - format
315
- - timeZone
316
- - maxDate
317
- - minDate
318
- - isRequired
319
- - emptyAsNull
320
- - defaultValue
321
- - badTypeMessage
285
+ Salida:
322
286
 
323
- Comportamiento clave:
287
+ - `VDate`: `datetime.Dayjs | null`
288
+ - `VDateNotNull`: `datetime.Dayjs`
324
289
 
325
- - Entradas soportadas: number, string, Date y datetime.Dayjs.
326
- - Si no defines timeZone usa UTC por defecto.
327
- - Si format no incluye zona horaria, se aplica la zona configurada.
290
+ Reglas:
328
291
 
329
- Ejemplo:
292
+ - `format`
293
+ - `timeZone`
294
+ - `maxDate`
295
+ - `minDate`
296
+ - reglas transversales
330
297
 
331
- ```ts
332
- import { Verifiers as V, datetime } from "structure-verifier";
298
+ Comportamiento importante:
333
299
 
334
- const dateV = V.DateNotNull()
335
- .format("YYYY-MM-DD")
336
- .timeZone("America/Mexico_City")
337
- .minDate(datetime("2024-01-01"));
300
+ - Soporta entrada `number`, `string`, `Date` y `datetime.Dayjs`.
301
+ - Si no defines `timeZone`, usa `UTC`.
302
+ - Si el `format` no incluye zona horaria, aplica la zona configurada.
338
303
 
339
- const d = dateV.check("2025-05-10");
340
- ```
304
+ ### Array / ArrayNotNull
341
305
 
342
- ### Array y ArrayNotNull
306
+ Salida:
343
307
 
344
- Firma:
308
+ - `VArray`: `ReturnType<T["check"]>[] | null`
309
+ - `VArrayNotNull`: `ReturnType<T["check"]>[]`
345
310
 
346
- ```ts
347
- const tagsV = V.Array(V.StringNotNull(), { minLength: 1 });
348
- const tagsRequiredV = V.ArrayNotNull(V.StringNotNull(), { minLength: 1 });
349
- ```
311
+ Reglas:
350
312
 
351
- Retorno:
313
+ - `minLength`
314
+ - `maxLength`
315
+ - reglas transversales
352
316
 
353
- - VArray: ReturnType<T["check"]>[] | null
354
- - VArrayNotNull: ReturnType<T["check"]>[]
355
-
356
- Condiciones:
357
-
358
- - minLength
359
- - maxLength
360
- - isRequired
361
- - emptyAsNull
362
- - defaultValue
363
- - badTypeMessage
364
-
365
- Comportamiento clave:
317
+ Comportamiento importante:
366
318
 
367
319
  - Valida item por item con el verificador interno.
368
- - En errores anidados agrega rutas como [0], [1].name.
369
-
370
- ### Object y ObjectNotNull
320
+ - En errores anidados agrega rutas como `[0]`, `[1].name`, etc.
371
321
 
372
- Firma:
373
-
374
- ```ts
375
- const userV = V.Object(
376
- {
377
- name: V.StringNotNull(),
378
- age: V.Number(),
379
- },
380
- {
381
- strictMode: true,
382
- ignoreCase: false,
383
- takeAllValues: false,
384
- },
385
- );
386
- ```
322
+ ### Object / ObjectNotNull
387
323
 
388
- Retorno:
324
+ Salida:
389
325
 
390
- - VObject: objeto tipado | null
391
- - VObjectNotNull: objeto tipado
326
+ - `VObject`: objeto tipado o `null`
327
+ - `VObjectNotNull`: objeto tipado
392
328
 
393
- Condiciones:
329
+ Reglas:
394
330
 
395
- - invalidPropertyMessage
396
- - strictMode
397
- - ignoreCase
398
- - takeAllValues
399
- - conds
400
- - isRequired
401
- - emptyAsNull
402
- - defaultValue
403
- - badTypeMessage
331
+ - `invalidPropertyMessage`
332
+ - `strictMode`
333
+ - `ignoreCase`
334
+ - `takeAllValues`
335
+ - `conds`
336
+ - reglas transversales
404
337
 
405
- Comportamiento clave:
338
+ Comportamiento importante:
406
339
 
407
- - strictMode rechaza propiedades no declaradas.
408
- - ignoreCase permite mapear llaves sin distinguir mayusculas.
409
- - takeAllValues conserva propiedades extra en la salida.
410
- - conds ejecuta una validacion final con el objeto ya validado.
340
+ - `strictMode`: rechaza propiedades no declaradas.
341
+ - `ignoreCase`: permite mapear llaves sin distinguir mayusculas/minusculas.
342
+ - `takeAllValues`: conserva propiedades extra en la salida.
343
+ - `conds`: ejecuta validacion de negocio final sobre el objeto ya validado.
411
344
 
412
345
  ### Any
413
346
 
414
- Retorno:
347
+ Salida:
415
348
 
416
- - VAny: any | null
349
+ - `VAny`: `any | null`
417
350
 
418
- Condiciones:
351
+ Reglas:
419
352
 
420
- - isRequired
421
- - emptyAsNull
422
- - defaultValue
423
- - badTypeMessage
353
+ - reglas transversales
424
354
 
425
- ## Transformaciones de valores
355
+ ## Transformaciones
426
356
 
427
- La clase base Verifier incluye transform(mapper), que permite postprocesar la salida validada sin perder la validacion previa.
357
+ La clase base `Verifier` incluye `transform(mapper)` para postprocesar salida validada.
428
358
 
429
- String y StringNotNull incluyen helpers listos:
359
+ `VString` y `VStringNotNull` incluyen helpers:
430
360
 
431
- - trim
432
- - trimStart
433
- - trimEnd
434
- - toLowerCase
435
- - toUpperCase
436
- - removeAccents
437
- - padStart
438
- - padEnd
439
-
440
- Ejemplo:
361
+ - `trim`
362
+ - `trimStart`
363
+ - `trimEnd`
364
+ - `toLowerCase`
365
+ - `toUpperCase`
366
+ - `removeAccents`
367
+ - `padStart`
368
+ - `padEnd`
441
369
 
442
370
  ```ts
443
371
  const usernameV = V.StringNotNull({ minLength: 3 })
@@ -475,39 +403,53 @@ type NumberRequired = InferFactoryType<typeof V.NumberNotNull>;
475
403
 
476
404
  ## Manejo de errores
477
405
 
478
- Cuando una validacion falla se lanza VerificationError.
406
+ Cuando una validacion falla se lanza `VerificationError`.
479
407
 
480
- Propiedades principales:
408
+ Campos principales:
481
409
 
482
- - message: todos los errores concatenados por punto y coma.
483
- - errors: arreglo de mensajes planos.
484
- - errorsObj: arreglo de objetos con key, message y metadatos.
410
+ - `message`: string unico con errores concatenados por `;`.
411
+ - `errors`: arreglo de mensajes planos.
412
+ - `errorsObj`: arreglo con `key`, `message` y metadatos.
485
413
 
486
414
  Ejemplo:
487
415
 
488
416
  ```ts
417
+ import { Verifiers as V, VerificationError } from "structure-verifier";
418
+
489
419
  try {
490
- V.ObjectNotNull({
491
- name: V.StringNotNull({ minLength: 3 }),
492
- tags: V.ArrayNotNull(V.StringNotNull(), { minLength: 1 }),
493
- }).check({ name: "Al", tags: [] });
420
+ V.ObjectNotNull(
421
+ {
422
+ name: V.StringNotNull({ minLength: 3 }),
423
+ tags: V.ArrayNotNull(V.StringNotNull(), { minLength: 1 }),
424
+ },
425
+ { strictMode: true },
426
+ ).check({ name: "Al", tags: [], extra: true });
494
427
  } catch (error) {
495
428
  if (error instanceof VerificationError) {
429
+ console.log(error.message);
496
430
  console.log(error.errors);
497
431
  console.log(error.errorsObj);
498
432
  }
499
433
  }
500
434
  ```
501
435
 
502
- ## datetime (dayjs)
436
+ Posible salida en `errorsObj`:
503
437
 
504
- La libreria exporta dayjs como datetime con plugins activados:
438
+ ```ts
439
+ [
440
+ { key: "name", message: "debe tener una longitud minima de 3" },
441
+ { key: "tags", message: "debe tener al menos 1 elementos" },
442
+ { key: "extra", message: "no es una propiedad valida" },
443
+ ];
444
+ ```
505
445
 
506
- - utc
507
- - timezone
508
- - customParseFormat
446
+ ## datetime (dayjs)
509
447
 
510
- Ejemplo:
448
+ La libreria exporta `dayjs` como `datetime` con plugins habilitados:
449
+
450
+ - `utc`
451
+ - `timezone`
452
+ - `customParseFormat`
511
453
 
512
454
  ```ts
513
455
  import { datetime } from "structure-verifier";
@@ -517,53 +459,14 @@ const utc = now.tz("UTC").format();
517
459
  console.log(utc);
518
460
  ```
519
461
 
520
- ## Ejemplos avanzados
521
-
522
- ### Validacion de payload API
523
-
524
- ```ts
525
- const createOrderV = V.ObjectNotNull(
526
- {
527
- customerId: V.UUIDNotNull({ version: 4 }),
528
- items: V.ArrayNotNull(
529
- V.ObjectNotNull({
530
- sku: V.StringNotNull({ minLength: 1 }),
531
- quantity: V.NumberNotNull({ min: 1 }),
532
- }),
533
- { minLength: 1 },
534
- ),
535
- createdAt: V.DateNotNull().timeZone("UTC"),
536
- },
537
- {
538
- strictMode: true,
539
- },
540
- );
541
- ```
542
-
543
- ### conds para reglas de negocio
462
+ ## Buenas practicas para v1.0.0
544
463
 
545
- ```ts
546
- const personV = V.ObjectNotNull(
547
- {
548
- age: V.NumberNotNull({ min: 0 }),
549
- hasParentalConsent: V.Boolean(),
550
- },
551
- {
552
- conds: (value) => {
553
- if (value.age < 18 && value.hasParentalConsent !== true) {
554
- throw new Error("Parental consent is required for minors");
555
- }
556
- },
557
- },
558
- );
559
- ```
560
-
561
- ## Scripts de desarrollo
562
-
563
- ```bash
564
- npm test
565
- npm run dev
566
- ```
464
+ - Define siempre `strictMode: true` en payloads de entrada externa.
465
+ - Usa variantes `NotNull` en campos de negocio obligatorios.
466
+ - Agrega reglas semanticas con `conds` para validaciones cruzadas.
467
+ - Encadena normalizaciones (`trim`, `toLowerCase`, etc.) para salida consistente.
468
+ - Centraliza mensajes custom cuando quieras UX de errores uniforme.
469
+ - Cubre cada esquema critico con pruebas de casos validos e invalidos.
567
470
 
568
471
  ## Licencia
569
472
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "structure-verifier",
3
- "version": "0.0.17",
3
+ "version": "1.0.0",
4
4
  "description": "",
5
5
  "main": "dist/index.js",
6
6
  "repository": {