alado 2.2.5 → 2.2.7
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 +191 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -21,6 +21,7 @@
|
|
|
21
21
|
- [withAuth](#withauth)
|
|
22
22
|
- [DTOs](#dtos)
|
|
23
23
|
- [validateProperty](#validateproperty)
|
|
24
|
+
- [validation](#validation)
|
|
24
25
|
- [documentProperty](#documentproperty)
|
|
25
26
|
- [transformProperty](#transformproperty)
|
|
26
27
|
- [fileUploadProperty](#fileuploadproperty)
|
|
@@ -402,6 +403,196 @@ class CredentialsDto {
|
|
|
402
403
|
|
|
403
404
|
---
|
|
404
405
|
|
|
406
|
+
## Validation
|
|
407
|
+
|
|
408
|
+
The project uses a built-in chainable validator — a lightweight Joi-like class with zero dependencies.
|
|
409
|
+
|
|
410
|
+
### Basic usage
|
|
411
|
+
|
|
412
|
+
```ts
|
|
413
|
+
import { validate } from 'alado';
|
|
414
|
+
|
|
415
|
+
const isEmail = validate.string().email().required().build();
|
|
416
|
+
const isUsername = validate
|
|
417
|
+
.string()
|
|
418
|
+
.min(3)
|
|
419
|
+
.max(20)
|
|
420
|
+
.regex(/^[a-z0-9_]+$/)
|
|
421
|
+
.build();
|
|
422
|
+
const isRole = validate.string().enum('admin', 'user', 'guest').required().build();
|
|
423
|
+
const isAge = validate.number().integer().min(18).max(120).required().build();
|
|
424
|
+
const isId = validate.objectId().required().build();
|
|
425
|
+
```
|
|
426
|
+
|
|
427
|
+
Each chain ends with `.build()` which returns a plain `(input: any) => boolean` function — build once, reuse anywhere.
|
|
428
|
+
|
|
429
|
+
---
|
|
430
|
+
|
|
431
|
+
### Available rules
|
|
432
|
+
|
|
433
|
+
**Type**
|
|
434
|
+
|
|
435
|
+
| Method | Description |
|
|
436
|
+
| ----------- | -------------------------- |
|
|
437
|
+
| `string()` | Must be a string |
|
|
438
|
+
| `number()` | Must be a number (not NaN) |
|
|
439
|
+
| `boolean()` | Must be a boolean |
|
|
440
|
+
| `array()` | Must be an array |
|
|
441
|
+
| `object()` | Must be a plain object |
|
|
442
|
+
|
|
443
|
+
**String**
|
|
444
|
+
|
|
445
|
+
| Method | Description |
|
|
446
|
+
| ---------------- | ----------------------------------------- |
|
|
447
|
+
| `min(n)` | Min length (string) or min value (number) |
|
|
448
|
+
| `max(n)` | Max length (string) or max value (number) |
|
|
449
|
+
| `length(n)` | Exact length |
|
|
450
|
+
| `regex(pattern)` | Must match pattern |
|
|
451
|
+
| `email()` | Valid email format |
|
|
452
|
+
| `uuid()` | Valid UUID v4 |
|
|
453
|
+
| `objectId()` | Valid MongoDB ObjectId (24-char hex) |
|
|
454
|
+
| `url()` | Valid URL |
|
|
455
|
+
| `trim()` | Must have no leading/trailing whitespace |
|
|
456
|
+
|
|
457
|
+
**Number**
|
|
458
|
+
|
|
459
|
+
| Method | Description |
|
|
460
|
+
| ------------ | ------------------ |
|
|
461
|
+
| `integer()` | Must be an integer |
|
|
462
|
+
| `positive()` | Must be > 0 |
|
|
463
|
+
| `negative()` | Must be < 0 |
|
|
464
|
+
|
|
465
|
+
**Generic**
|
|
466
|
+
|
|
467
|
+
| Method | Description |
|
|
468
|
+
| ----------------- | --------------------------------------------- |
|
|
469
|
+
| `enum(...values)` | Must be one of the provided values |
|
|
470
|
+
| `custom(fn)` | Any custom `(value) => boolean` function |
|
|
471
|
+
| `required()` | Reject `null`, `undefined`, and `''` |
|
|
472
|
+
| `optional()` | Allow `null`, `undefined`, and `''` (default) |
|
|
473
|
+
|
|
474
|
+
**Object**
|
|
475
|
+
|
|
476
|
+
| Method | Description |
|
|
477
|
+
| --------------- | -------------------------------------------- |
|
|
478
|
+
| `shape(schema)` | Validate each key against a nested validator |
|
|
479
|
+
|
|
480
|
+
**Array**
|
|
481
|
+
|
|
482
|
+
| Method | Description |
|
|
483
|
+
| ------------- | ------------------------------------- |
|
|
484
|
+
| `items(fn)` | Every element must pass the validator |
|
|
485
|
+
| `minItems(n)` | Minimum array length |
|
|
486
|
+
| `maxItems(n)` | Maximum array length |
|
|
487
|
+
| `unique()` | No duplicate values |
|
|
488
|
+
|
|
489
|
+
---
|
|
490
|
+
|
|
491
|
+
### Object shape
|
|
492
|
+
|
|
493
|
+
```ts
|
|
494
|
+
const isAddress = validate
|
|
495
|
+
.object()
|
|
496
|
+
.shape({
|
|
497
|
+
street: validate.string().min(2).required().build(),
|
|
498
|
+
city: validate.string().min(2).required().build(),
|
|
499
|
+
country: validate.string().length(2).required().build(),
|
|
500
|
+
zip: validate
|
|
501
|
+
.string()
|
|
502
|
+
.regex(/^\d{4,10}$/)
|
|
503
|
+
.build(),
|
|
504
|
+
})
|
|
505
|
+
.required()
|
|
506
|
+
.build();
|
|
507
|
+
```
|
|
508
|
+
|
|
509
|
+
Shapes can be nested to any depth:
|
|
510
|
+
|
|
511
|
+
```ts
|
|
512
|
+
const isUser = validate
|
|
513
|
+
.object()
|
|
514
|
+
.shape({
|
|
515
|
+
id: validate.objectId().required().build(),
|
|
516
|
+
email: validate.string().email().required().build(),
|
|
517
|
+
role: validate.string().enum('admin', 'user').required().build(),
|
|
518
|
+
address: validate
|
|
519
|
+
.object()
|
|
520
|
+
.shape({
|
|
521
|
+
city: validate.string().required().build(),
|
|
522
|
+
country: validate.string().length(2).required().build(),
|
|
523
|
+
})
|
|
524
|
+
.build(),
|
|
525
|
+
})
|
|
526
|
+
.required()
|
|
527
|
+
.build();
|
|
528
|
+
```
|
|
529
|
+
|
|
530
|
+
---
|
|
531
|
+
|
|
532
|
+
### Array items
|
|
533
|
+
|
|
534
|
+
```ts
|
|
535
|
+
const isTagList = validate
|
|
536
|
+
.array()
|
|
537
|
+
.items(validate.string().min(1).max(30).required().build())
|
|
538
|
+
.minItems(1)
|
|
539
|
+
.maxItems(10)
|
|
540
|
+
.unique()
|
|
541
|
+
.required()
|
|
542
|
+
.build();
|
|
543
|
+
|
|
544
|
+
const isOrderItems = validate
|
|
545
|
+
.array()
|
|
546
|
+
.items(
|
|
547
|
+
validate
|
|
548
|
+
.object()
|
|
549
|
+
.shape({
|
|
550
|
+
productId: validate.objectId().required().build(),
|
|
551
|
+
quantity: validate.number().integer().positive().required().build(),
|
|
552
|
+
price: validate.number().positive().required().build(),
|
|
553
|
+
})
|
|
554
|
+
.required()
|
|
555
|
+
.build(),
|
|
556
|
+
)
|
|
557
|
+
.minItems(1)
|
|
558
|
+
.required()
|
|
559
|
+
.build();
|
|
560
|
+
```
|
|
561
|
+
|
|
562
|
+
---
|
|
563
|
+
|
|
564
|
+
### Use with Alado `@validateProperty`
|
|
565
|
+
|
|
566
|
+
```ts
|
|
567
|
+
import { documentProperty, validateProperty, validate } from 'alado';
|
|
568
|
+
|
|
569
|
+
export class CredentialsDto {
|
|
570
|
+
@validateProperty({
|
|
571
|
+
required: true,
|
|
572
|
+
handler: validate.string().email().required().build(),
|
|
573
|
+
error: { statusCode: 400, message: 'Invalid email' },
|
|
574
|
+
})
|
|
575
|
+
@documentProperty({
|
|
576
|
+
schema: { type: 'string', format: 'email' },
|
|
577
|
+
example: 'user@example.com',
|
|
578
|
+
})
|
|
579
|
+
email: string = '';
|
|
580
|
+
|
|
581
|
+
@validateProperty({
|
|
582
|
+
required: true,
|
|
583
|
+
handler: validate.string().min(8).required().build(),
|
|
584
|
+
error: { statusCode: 400, message: 'Password must be at least 8 characters' },
|
|
585
|
+
})
|
|
586
|
+
@documentProperty({
|
|
587
|
+
schema: { type: 'string', minLength: 8 },
|
|
588
|
+
example: 'securePassword',
|
|
589
|
+
})
|
|
590
|
+
password: string = '';
|
|
591
|
+
}
|
|
592
|
+
```
|
|
593
|
+
|
|
594
|
+
---
|
|
595
|
+
|
|
405
596
|
### `documentProperty`
|
|
406
597
|
|
|
407
598
|
Adds OpenAPI/Swagger metadata to a property.
|