alado 2.2.4 → 2.2.6

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 +193 -0
  2. 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
+ - [validate](#validate)
24
25
  - [documentProperty](#documentproperty)
25
26
  - [transformProperty](#transformproperty)
26
27
  - [fileUploadProperty](#fileuploadproperty)
@@ -108,6 +109,8 @@ app.start(() => console.log('Running on http://localhost:3000'));
108
109
 
109
110
  ---
110
111
 
112
+ ## Example API: https://github.com/databikers/alado-decorators-api-example
113
+
111
114
  ## Project Structure
112
115
 
113
116
  Possible layout for a decorator-based Alado project:
@@ -400,6 +403,196 @@ class CredentialsDto {
400
403
 
401
404
  ---
402
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
+
403
596
  ### `documentProperty`
404
597
 
405
598
  Adds OpenAPI/Swagger metadata to a property.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "alado",
3
- "version": "2.2.4",
3
+ "version": "2.2.6",
4
4
  "description": "Extremely fast, lightweight, robust framework for HTTP applications written in Node.js",
5
5
  "keywords": [
6
6
  "HTTP",