@fiado/type-kit 3.28.0 → 3.29.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/bin/messaging/dtos/MessageDeliveryRequest.js +5 -6
- package/bin/messaging/index.d.ts +2 -0
- package/bin/messaging/index.js +2 -0
- package/bin/messaging/validators/IsDestinationByChannel.d.ts +5 -0
- package/bin/messaging/validators/IsDestinationByChannel.js +69 -0
- package/bin/messaging/validators/IsNotBlank.d.ts +24 -0
- package/bin/messaging/validators/IsNotBlank.js +41 -0
- package/package.json +1 -1
- package/src/messaging/dtos/MessageDeliveryRequest.ts +6 -7
- package/src/messaging/index.ts +6 -4
- package/src/messaging/validators/IsDestinationByChannel.ts +61 -0
- package/src/messaging/validators/IsNotBlank.ts +31 -0
|
@@ -14,6 +14,8 @@ const class_transformer_1 = require("class-transformer");
|
|
|
14
14
|
const class_validator_1 = require("class-validator");
|
|
15
15
|
const DeliveryChannelEnum_1 = require("../enums/DeliveryChannelEnum");
|
|
16
16
|
const ContentTypeEnum_1 = require("../enums/ContentTypeEnum");
|
|
17
|
+
const IsDestinationByChannel_1 = require("../validators/IsDestinationByChannel");
|
|
18
|
+
const IsNotBlank_1 = require("../validators/IsNotBlank");
|
|
17
19
|
class MessageDeliveryRequest {
|
|
18
20
|
}
|
|
19
21
|
exports.MessageDeliveryRequest = MessageDeliveryRequest;
|
|
@@ -24,21 +26,18 @@ __decorate([
|
|
|
24
26
|
], MessageDeliveryRequest.prototype, "deliveryChannel", void 0);
|
|
25
27
|
__decorate([
|
|
26
28
|
(0, class_transformer_1.Expose)(),
|
|
27
|
-
(0, class_validator_1.
|
|
28
|
-
(0, class_validator_1.IsNotEmpty)(),
|
|
29
|
+
(0, class_validator_1.Validate)(IsDestinationByChannel_1.IsDestinationByChannel),
|
|
29
30
|
__metadata("design:type", String)
|
|
30
31
|
], MessageDeliveryRequest.prototype, "destination", void 0);
|
|
31
32
|
__decorate([
|
|
32
33
|
(0, class_transformer_1.Expose)(),
|
|
33
34
|
(0, class_validator_1.ValidateIf)(o => o.deliveryChannel === DeliveryChannelEnum_1.DeliveryChannelEnum.MAIL),
|
|
34
|
-
(0, class_validator_1.
|
|
35
|
-
(0, class_validator_1.IsNotEmpty)(),
|
|
35
|
+
(0, class_validator_1.Validate)(IsNotBlank_1.IsNotBlank),
|
|
36
36
|
__metadata("design:type", String)
|
|
37
37
|
], MessageDeliveryRequest.prototype, "subject", void 0);
|
|
38
38
|
__decorate([
|
|
39
39
|
(0, class_transformer_1.Expose)(),
|
|
40
|
-
(0, class_validator_1.
|
|
41
|
-
(0, class_validator_1.IsNotEmpty)(),
|
|
40
|
+
(0, class_validator_1.Validate)(IsNotBlank_1.IsNotBlank),
|
|
42
41
|
__metadata("design:type", String)
|
|
43
42
|
], MessageDeliveryRequest.prototype, "message", void 0);
|
|
44
43
|
__decorate([
|
package/bin/messaging/index.d.ts
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
export * from './enums/DeliveryChannelEnum';
|
|
2
2
|
export * from './enums/ContentTypeEnum';
|
|
3
|
+
export * from './validators/IsDestinationByChannel';
|
|
4
|
+
export * from './validators/IsNotBlank';
|
|
3
5
|
export * from './dtos/MessageDeliveryRequest';
|
|
4
6
|
export * from './dtos/MessageDeliveryResponse';
|
package/bin/messaging/index.js
CHANGED
|
@@ -16,5 +16,7 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
|
16
16
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
17
|
__exportStar(require("./enums/DeliveryChannelEnum"), exports);
|
|
18
18
|
__exportStar(require("./enums/ContentTypeEnum"), exports);
|
|
19
|
+
__exportStar(require("./validators/IsDestinationByChannel"), exports);
|
|
20
|
+
__exportStar(require("./validators/IsNotBlank"), exports);
|
|
19
21
|
__exportStar(require("./dtos/MessageDeliveryRequest"), exports);
|
|
20
22
|
__exportStar(require("./dtos/MessageDeliveryResponse"), exports);
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { ValidatorConstraintInterface, ValidationArguments } from 'class-validator';
|
|
2
|
+
export declare class IsDestinationByChannel implements ValidatorConstraintInterface {
|
|
3
|
+
validate(value: unknown, args: ValidationArguments): boolean;
|
|
4
|
+
defaultMessage(args: ValidationArguments): string;
|
|
5
|
+
}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
3
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
5
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
6
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
7
|
+
};
|
|
8
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
+
exports.IsDestinationByChannel = void 0;
|
|
10
|
+
const class_validator_1 = require("class-validator");
|
|
11
|
+
const DeliveryChannelEnum_1 = require("../enums/DeliveryChannelEnum");
|
|
12
|
+
/**
|
|
13
|
+
* Valida que `destination` matchee el formato correcto segun el `deliveryChannel`
|
|
14
|
+
* declarado en el mismo DTO.
|
|
15
|
+
*
|
|
16
|
+
* Por que un custom validator en lugar de dos `@ValidateIf` + `@IsEmail`/`@Matches`:
|
|
17
|
+
* - `@ValidateIf` afecta a **toda la propiedad**, no solo a los decoradores que
|
|
18
|
+
* vienen despues. Cuando se ponen dos `@ValidateIf` consecutivos sobre la
|
|
19
|
+
* misma propiedad, el segundo sobrescribe al primero y class-validator
|
|
20
|
+
* ignora silenciosamente los validators afectados.
|
|
21
|
+
* - Originalmente descubierto en `sns-ses-connector/tests/RUN_LOG.md` T7/T10/T11
|
|
22
|
+
* (2026-05-21) — la version anterior del DTO dejaba pasar
|
|
23
|
+
* `destination: "12345"` con canal SMS y `destination: "no-es-email"` con
|
|
24
|
+
* canal MAIL. Validator migrado del connector al type-kit en 3.29.0 para
|
|
25
|
+
* eliminar el DTO_LOCAL del connector y exponer la regla a todos los
|
|
26
|
+
* callers de `MessageDeliveryRequest`.
|
|
27
|
+
*
|
|
28
|
+
* Reglas:
|
|
29
|
+
* - Canal `SMS` → `destination` debe matchear E.164: `^\+\d{10,15}$`
|
|
30
|
+
* - Canal `MAIL` → `destination` debe matchear formato email
|
|
31
|
+
* - Canal invalido o ausente → falla (el `@IsEnum` del DTO genera su propio mensaje aparte)
|
|
32
|
+
* - String vacio o whitespace → falla
|
|
33
|
+
*
|
|
34
|
+
* Uso tipico:
|
|
35
|
+
* ```ts
|
|
36
|
+
* @Validate(IsDestinationByChannel)
|
|
37
|
+
* destination: string;
|
|
38
|
+
* ```
|
|
39
|
+
*/
|
|
40
|
+
const E164_REGEX = /^\+\d{10,15}$/;
|
|
41
|
+
const EMAIL_REGEX = /^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}$/;
|
|
42
|
+
let IsDestinationByChannel = class IsDestinationByChannel {
|
|
43
|
+
validate(value, args) {
|
|
44
|
+
if (typeof value !== 'string' || value.trim().length === 0)
|
|
45
|
+
return false;
|
|
46
|
+
const obj = args.object;
|
|
47
|
+
const channel = obj.deliveryChannel;
|
|
48
|
+
if (channel === DeliveryChannelEnum_1.DeliveryChannelEnum.SMS)
|
|
49
|
+
return E164_REGEX.test(value);
|
|
50
|
+
if (channel === DeliveryChannelEnum_1.DeliveryChannelEnum.MAIL)
|
|
51
|
+
return EMAIL_REGEX.test(value);
|
|
52
|
+
return false;
|
|
53
|
+
}
|
|
54
|
+
defaultMessage(args) {
|
|
55
|
+
const obj = args.object;
|
|
56
|
+
const channel = obj.deliveryChannel;
|
|
57
|
+
if (channel === DeliveryChannelEnum_1.DeliveryChannelEnum.SMS) {
|
|
58
|
+
return 'destination debe ser un telefono en formato E.164 (ej. +5215512345678) para canal SMS';
|
|
59
|
+
}
|
|
60
|
+
if (channel === DeliveryChannelEnum_1.DeliveryChannelEnum.MAIL) {
|
|
61
|
+
return 'destination debe ser un email valido para canal MAIL';
|
|
62
|
+
}
|
|
63
|
+
return 'destination requerido y debe corresponder al deliveryChannel';
|
|
64
|
+
}
|
|
65
|
+
};
|
|
66
|
+
exports.IsDestinationByChannel = IsDestinationByChannel;
|
|
67
|
+
exports.IsDestinationByChannel = IsDestinationByChannel = __decorate([
|
|
68
|
+
(0, class_validator_1.ValidatorConstraint)({ name: 'IsDestinationByChannel', async: false })
|
|
69
|
+
], IsDestinationByChannel);
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { ValidatorConstraintInterface, ValidationArguments } from 'class-validator';
|
|
2
|
+
/**
|
|
3
|
+
* Valida que el valor sea un string con al menos un caracter no-whitespace.
|
|
4
|
+
*
|
|
5
|
+
* Por que no usar `@IsNotEmpty()` de class-validator:
|
|
6
|
+
* - `@IsNotEmpty()` solo rechaza `""`, `null`, `undefined`, `false`, `0`.
|
|
7
|
+
* - **No** rechaza strings de solo whitespace (`" "`).
|
|
8
|
+
*
|
|
9
|
+
* En el sns-ses-connector eso era un bug latente: un `message: " "` pasaba la
|
|
10
|
+
* validacion, llegaba al SDK de SNS/SES, y se enviaba un SMS o email con
|
|
11
|
+
* contenido vacio al usuario final (y AWS cobraba). Originalmente descubierto
|
|
12
|
+
* en `sns-ses-connector/tests/RUN_LOG.md` T8b (2026-05-21). Validator migrado
|
|
13
|
+
* al type-kit en 3.29.0 para eliminar el DTO_LOCAL del connector.
|
|
14
|
+
*
|
|
15
|
+
* Uso tipico:
|
|
16
|
+
* ```ts
|
|
17
|
+
* @Validate(IsNotBlank)
|
|
18
|
+
* message: string;
|
|
19
|
+
* ```
|
|
20
|
+
*/
|
|
21
|
+
export declare class IsNotBlank implements ValidatorConstraintInterface {
|
|
22
|
+
validate(value: unknown, _args: ValidationArguments): boolean;
|
|
23
|
+
defaultMessage(args: ValidationArguments): string;
|
|
24
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
3
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
5
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
6
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
7
|
+
};
|
|
8
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
+
exports.IsNotBlank = void 0;
|
|
10
|
+
const class_validator_1 = require("class-validator");
|
|
11
|
+
/**
|
|
12
|
+
* Valida que el valor sea un string con al menos un caracter no-whitespace.
|
|
13
|
+
*
|
|
14
|
+
* Por que no usar `@IsNotEmpty()` de class-validator:
|
|
15
|
+
* - `@IsNotEmpty()` solo rechaza `""`, `null`, `undefined`, `false`, `0`.
|
|
16
|
+
* - **No** rechaza strings de solo whitespace (`" "`).
|
|
17
|
+
*
|
|
18
|
+
* En el sns-ses-connector eso era un bug latente: un `message: " "` pasaba la
|
|
19
|
+
* validacion, llegaba al SDK de SNS/SES, y se enviaba un SMS o email con
|
|
20
|
+
* contenido vacio al usuario final (y AWS cobraba). Originalmente descubierto
|
|
21
|
+
* en `sns-ses-connector/tests/RUN_LOG.md` T8b (2026-05-21). Validator migrado
|
|
22
|
+
* al type-kit en 3.29.0 para eliminar el DTO_LOCAL del connector.
|
|
23
|
+
*
|
|
24
|
+
* Uso tipico:
|
|
25
|
+
* ```ts
|
|
26
|
+
* @Validate(IsNotBlank)
|
|
27
|
+
* message: string;
|
|
28
|
+
* ```
|
|
29
|
+
*/
|
|
30
|
+
let IsNotBlank = class IsNotBlank {
|
|
31
|
+
validate(value, _args) {
|
|
32
|
+
return typeof value === 'string' && value.trim().length > 0;
|
|
33
|
+
}
|
|
34
|
+
defaultMessage(args) {
|
|
35
|
+
return `${args.property} no puede ser vacio ni solo espacios en blanco`;
|
|
36
|
+
}
|
|
37
|
+
};
|
|
38
|
+
exports.IsNotBlank = IsNotBlank;
|
|
39
|
+
exports.IsNotBlank = IsNotBlank = __decorate([
|
|
40
|
+
(0, class_validator_1.ValidatorConstraint)({ name: 'IsNotBlank', async: false })
|
|
41
|
+
], IsNotBlank);
|
package/package.json
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import { Expose } from 'class-transformer';
|
|
2
|
-
import { IsEnum,
|
|
2
|
+
import { IsEnum, Validate, ValidateIf } from 'class-validator';
|
|
3
3
|
import { DeliveryChannelEnum } from '../enums/DeliveryChannelEnum';
|
|
4
4
|
import { ContentTypeEnum } from '../enums/ContentTypeEnum';
|
|
5
|
+
import { IsDestinationByChannel } from '../validators/IsDestinationByChannel';
|
|
6
|
+
import { IsNotBlank } from '../validators/IsNotBlank';
|
|
5
7
|
|
|
6
8
|
export class MessageDeliveryRequest {
|
|
7
9
|
@Expose()
|
|
@@ -9,19 +11,16 @@ export class MessageDeliveryRequest {
|
|
|
9
11
|
deliveryChannel: DeliveryChannelEnum;
|
|
10
12
|
|
|
11
13
|
@Expose()
|
|
12
|
-
@
|
|
13
|
-
@IsNotEmpty()
|
|
14
|
+
@Validate(IsDestinationByChannel)
|
|
14
15
|
destination: string;
|
|
15
16
|
|
|
16
17
|
@Expose()
|
|
17
18
|
@ValidateIf(o => o.deliveryChannel === DeliveryChannelEnum.MAIL)
|
|
18
|
-
@
|
|
19
|
-
@IsNotEmpty()
|
|
19
|
+
@Validate(IsNotBlank)
|
|
20
20
|
subject: string;
|
|
21
21
|
|
|
22
22
|
@Expose()
|
|
23
|
-
@
|
|
24
|
-
@IsNotEmpty()
|
|
23
|
+
@Validate(IsNotBlank)
|
|
25
24
|
message: string;
|
|
26
25
|
|
|
27
26
|
@Expose()
|
package/src/messaging/index.ts
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
export * from './enums/DeliveryChannelEnum';
|
|
2
|
-
export * from './enums/ContentTypeEnum';
|
|
3
|
-
export * from './
|
|
4
|
-
export * from './
|
|
1
|
+
export * from './enums/DeliveryChannelEnum';
|
|
2
|
+
export * from './enums/ContentTypeEnum';
|
|
3
|
+
export * from './validators/IsDestinationByChannel';
|
|
4
|
+
export * from './validators/IsNotBlank';
|
|
5
|
+
export * from './dtos/MessageDeliveryRequest';
|
|
6
|
+
export * from './dtos/MessageDeliveryResponse';
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { ValidatorConstraint, ValidatorConstraintInterface, ValidationArguments } from 'class-validator';
|
|
2
|
+
import { DeliveryChannelEnum } from '../enums/DeliveryChannelEnum';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Valida que `destination` matchee el formato correcto segun el `deliveryChannel`
|
|
6
|
+
* declarado en el mismo DTO.
|
|
7
|
+
*
|
|
8
|
+
* Por que un custom validator en lugar de dos `@ValidateIf` + `@IsEmail`/`@Matches`:
|
|
9
|
+
* - `@ValidateIf` afecta a **toda la propiedad**, no solo a los decoradores que
|
|
10
|
+
* vienen despues. Cuando se ponen dos `@ValidateIf` consecutivos sobre la
|
|
11
|
+
* misma propiedad, el segundo sobrescribe al primero y class-validator
|
|
12
|
+
* ignora silenciosamente los validators afectados.
|
|
13
|
+
* - Originalmente descubierto en `sns-ses-connector/tests/RUN_LOG.md` T7/T10/T11
|
|
14
|
+
* (2026-05-21) — la version anterior del DTO dejaba pasar
|
|
15
|
+
* `destination: "12345"` con canal SMS y `destination: "no-es-email"` con
|
|
16
|
+
* canal MAIL. Validator migrado del connector al type-kit en 3.29.0 para
|
|
17
|
+
* eliminar el DTO_LOCAL del connector y exponer la regla a todos los
|
|
18
|
+
* callers de `MessageDeliveryRequest`.
|
|
19
|
+
*
|
|
20
|
+
* Reglas:
|
|
21
|
+
* - Canal `SMS` → `destination` debe matchear E.164: `^\+\d{10,15}$`
|
|
22
|
+
* - Canal `MAIL` → `destination` debe matchear formato email
|
|
23
|
+
* - Canal invalido o ausente → falla (el `@IsEnum` del DTO genera su propio mensaje aparte)
|
|
24
|
+
* - String vacio o whitespace → falla
|
|
25
|
+
*
|
|
26
|
+
* Uso tipico:
|
|
27
|
+
* ```ts
|
|
28
|
+
* @Validate(IsDestinationByChannel)
|
|
29
|
+
* destination: string;
|
|
30
|
+
* ```
|
|
31
|
+
*/
|
|
32
|
+
const E164_REGEX = /^\+\d{10,15}$/;
|
|
33
|
+
const EMAIL_REGEX = /^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}$/;
|
|
34
|
+
|
|
35
|
+
@ValidatorConstraint({ name: 'IsDestinationByChannel', async: false })
|
|
36
|
+
export class IsDestinationByChannel implements ValidatorConstraintInterface {
|
|
37
|
+
validate(value: unknown, args: ValidationArguments): boolean {
|
|
38
|
+
if (typeof value !== 'string' || value.trim().length === 0) return false;
|
|
39
|
+
|
|
40
|
+
const obj = args.object as { deliveryChannel?: unknown };
|
|
41
|
+
const channel = obj.deliveryChannel;
|
|
42
|
+
|
|
43
|
+
if (channel === DeliveryChannelEnum.SMS) return E164_REGEX.test(value);
|
|
44
|
+
if (channel === DeliveryChannelEnum.MAIL) return EMAIL_REGEX.test(value);
|
|
45
|
+
|
|
46
|
+
return false;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
defaultMessage(args: ValidationArguments): string {
|
|
50
|
+
const obj = args.object as { deliveryChannel?: unknown };
|
|
51
|
+
const channel = obj.deliveryChannel;
|
|
52
|
+
|
|
53
|
+
if (channel === DeliveryChannelEnum.SMS) {
|
|
54
|
+
return 'destination debe ser un telefono en formato E.164 (ej. +5215512345678) para canal SMS';
|
|
55
|
+
}
|
|
56
|
+
if (channel === DeliveryChannelEnum.MAIL) {
|
|
57
|
+
return 'destination debe ser un email valido para canal MAIL';
|
|
58
|
+
}
|
|
59
|
+
return 'destination requerido y debe corresponder al deliveryChannel';
|
|
60
|
+
}
|
|
61
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { ValidatorConstraint, ValidatorConstraintInterface, ValidationArguments } from 'class-validator';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Valida que el valor sea un string con al menos un caracter no-whitespace.
|
|
5
|
+
*
|
|
6
|
+
* Por que no usar `@IsNotEmpty()` de class-validator:
|
|
7
|
+
* - `@IsNotEmpty()` solo rechaza `""`, `null`, `undefined`, `false`, `0`.
|
|
8
|
+
* - **No** rechaza strings de solo whitespace (`" "`).
|
|
9
|
+
*
|
|
10
|
+
* En el sns-ses-connector eso era un bug latente: un `message: " "` pasaba la
|
|
11
|
+
* validacion, llegaba al SDK de SNS/SES, y se enviaba un SMS o email con
|
|
12
|
+
* contenido vacio al usuario final (y AWS cobraba). Originalmente descubierto
|
|
13
|
+
* en `sns-ses-connector/tests/RUN_LOG.md` T8b (2026-05-21). Validator migrado
|
|
14
|
+
* al type-kit en 3.29.0 para eliminar el DTO_LOCAL del connector.
|
|
15
|
+
*
|
|
16
|
+
* Uso tipico:
|
|
17
|
+
* ```ts
|
|
18
|
+
* @Validate(IsNotBlank)
|
|
19
|
+
* message: string;
|
|
20
|
+
* ```
|
|
21
|
+
*/
|
|
22
|
+
@ValidatorConstraint({ name: 'IsNotBlank', async: false })
|
|
23
|
+
export class IsNotBlank implements ValidatorConstraintInterface {
|
|
24
|
+
validate(value: unknown, _args: ValidationArguments): boolean {
|
|
25
|
+
return typeof value === 'string' && value.trim().length > 0;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
defaultMessage(args: ValidationArguments): string {
|
|
29
|
+
return `${args.property} no puede ser vacio ni solo espacios en blanco`;
|
|
30
|
+
}
|
|
31
|
+
}
|