@fiado/type-kit 3.418.0 → 3.419.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/_test_/unit/messagesConnector/NotificationQueueMessageRequestV2.test.ts +27 -10
- package/bin/messagesConnector/constants/MessageIdempotencyLimits.d.ts +5 -0
- package/bin/messagesConnector/constants/MessageIdempotencyLimits.js +8 -0
- package/bin/messagesConnector/dtos/NotificationQueueMessageRequestV2.d.ts +11 -3
- package/bin/messagesConnector/dtos/NotificationQueueMessageRequestV2.js +10 -0
- package/bin/messagesConnector/index.d.ts +1 -0
- package/bin/messagesConnector/index.js +1 -0
- package/package.json +1 -1
- package/src/messagesConnector/constants/MessageIdempotencyLimits.ts +5 -0
- package/src/messagesConnector/dtos/NotificationQueueMessageRequestV2.ts +20 -4
- package/src/messagesConnector/index.ts +1 -0
|
@@ -4,6 +4,7 @@ import { validate } from 'class-validator';
|
|
|
4
4
|
import { NotificationQueueMessageRequestV2 } from '../../../src/messagesConnector/dtos/NotificationQueueMessageRequestV2';
|
|
5
5
|
import { NotificationOriginEnum } from '../../../src/messagesConnector/enums/NotificationOriginEnum';
|
|
6
6
|
import { DeliveryChannelExtendedEnum } from '../../../src/messagesConnector/enums/DeliveryChannelExtendedEnum';
|
|
7
|
+
import { MESSAGE_IDEMPOTENCY_KEY_MAX_LENGTH } from '../../../src/messagesConnector/constants/MessageIdempotencyLimits';
|
|
7
8
|
|
|
8
9
|
const base = {
|
|
9
10
|
templateId: 'OTP_CODE',
|
|
@@ -48,7 +49,7 @@ describe('NotificationQueueMessageRequestV2.origin', () => {
|
|
|
48
49
|
});
|
|
49
50
|
});
|
|
50
51
|
|
|
51
|
-
describe('
|
|
52
|
+
describe('idempotencyKey — la llave de deduplicacion, aparte de la correlacion', () => {
|
|
52
53
|
const validQueueMessage = {
|
|
53
54
|
templateId: 'COLLECTION_PRE_DUE_2_DAYS',
|
|
54
55
|
channelType: DeliveryChannelExtendedEnum.SMS,
|
|
@@ -59,19 +60,35 @@ describe('referenceMessageId — la llave de idempotencia de la cola', () => {
|
|
|
59
60
|
destination: '+525512345678',
|
|
60
61
|
variables: { name: 'Ana' },
|
|
61
62
|
};
|
|
63
|
+
const build = (over: Record<string, unknown> = {}) =>
|
|
64
|
+
plainToInstance(NotificationQueueMessageRequestV2, { ...validQueueMessage, ...over });
|
|
62
65
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
it('acepta una referencia que no es UUID', async () => {
|
|
66
|
-
const dto = plainToInstance(NotificationQueueMessageRequestV2,
|
|
67
|
-
{ ...validQueueMessage, referenceMessageId: 'collections-2026-09-09-MORNING-0001' });
|
|
68
|
-
expect(await validate(dto)).toEqual([]);
|
|
66
|
+
it('acepta una llave de negocio que no es UUID', async () => {
|
|
67
|
+
expect(await validate(build({ idempotencyKey: 'run-42:credit-7:PRE_DUE_2_DAYS' }))).toEqual([]);
|
|
69
68
|
});
|
|
70
69
|
|
|
71
|
-
|
|
72
|
-
|
|
70
|
+
// Sin llave no hay deduplicacion: es el comportamiento de todos los productores de hoy.
|
|
71
|
+
it('sigue valido sin llave', async () => {
|
|
72
|
+
const dto = build();
|
|
73
73
|
expect(await validate(dto)).toEqual([]);
|
|
74
|
-
expect(dto.
|
|
74
|
+
expect(dto.idempotencyKey).toBeUndefined();
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
// El `#` separa los tramos de la llave de MessageLogs_GT: adentro la haria ambigua.
|
|
78
|
+
it('rechaza una llave con "#"', async () => {
|
|
79
|
+
const errors = await validate(build({ idempotencyKey: 'run-42#credit-7' }));
|
|
80
|
+
expect(errors.some((e) => e.property === 'idempotencyKey' && e.constraints?.matches)).toBe(true);
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
it('rechaza una llave sin techo', async () => {
|
|
84
|
+
const errors = await validate(build({ idempotencyKey: 'x'.repeat(MESSAGE_IDEMPOTENCY_KEY_MAX_LENGTH + 1) }));
|
|
85
|
+
expect(errors.some((e) => e.property === 'idempotencyKey' && e.constraints?.maxLength)).toBe(true);
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
// referenceMessageId trae el id de la CORRIDA, no del mensaje: deduplicar con el aplastaria
|
|
89
|
+
// en uno todos los avisos de un mismo barrido.
|
|
90
|
+
it('referenceMessageId es correlacion y NO tiene las restricciones de la llave', async () => {
|
|
91
|
+
expect(await validate(build({ referenceMessageId: 'run-42#lo-que-sea' }))).toEqual([]);
|
|
75
92
|
});
|
|
76
93
|
|
|
77
94
|
it('ya no acepta messageLogId: era plomeria del lote retirado', () => {
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.MESSAGE_IDEMPOTENCY_KEY_MAX_LENGTH = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* Largo maximo de la llave de idempotencia de un mensaje de la cola. Entra en la llave de
|
|
6
|
+
* `MessageLogs_GT`, asi que acotarla es lo que evita una llave sin techo.
|
|
7
|
+
*/
|
|
8
|
+
exports.MESSAGE_IDEMPOTENCY_KEY_MAX_LENGTH = 128;
|
|
@@ -11,11 +11,19 @@ export declare class NotificationQueueMessageRequestV2 {
|
|
|
11
11
|
directoryId: string;
|
|
12
12
|
destination: string;
|
|
13
13
|
variables: Record<string, string>;
|
|
14
|
+
/** Referencia de correlacion del productor. NO deduplica: para eso esta `idempotencyKey`. */
|
|
15
|
+
referenceMessageId?: string;
|
|
14
16
|
/**
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
+
* Llave de idempotencia, opcional y explicita. Cuando viaja, messages-business entrega UNA
|
|
18
|
+
* sola vez el trio (tenantId, idempotencyKey, channelType).
|
|
19
|
+
*
|
|
20
|
+
* Va aparte de `referenceMessageId` a proposito: esa referencia identifica la CORRIDA que
|
|
21
|
+
* produjo el mensaje, no al mensaje, asi que usarla para deduplicar aplastaria en uno todos
|
|
22
|
+
* los avisos de un mismo barrido. La llave tiene que distinguir al destinatario.
|
|
23
|
+
*
|
|
24
|
+
* Un `#` en el valor hace ambigua la llave: no se admite.
|
|
17
25
|
*/
|
|
18
|
-
|
|
26
|
+
idempotencyKey?: string;
|
|
19
27
|
data?: unknown;
|
|
20
28
|
/** Quien disparo la notificacion. Sin default: su ausencia ya significa EVENT. */
|
|
21
29
|
origin?: NotificationOriginEnum;
|
|
@@ -15,6 +15,7 @@ const class_transformer_1 = require("class-transformer");
|
|
|
15
15
|
const DeliveryChannelExtendedEnum_1 = require("../enums/DeliveryChannelExtendedEnum");
|
|
16
16
|
const NotificationOriginEnum_1 = require("../enums/NotificationOriginEnum");
|
|
17
17
|
const IsStringValueRecord_1 = require("../validators/IsStringValueRecord");
|
|
18
|
+
const MessageIdempotencyLimits_1 = require("../constants/MessageIdempotencyLimits");
|
|
18
19
|
class NotificationQueueMessageRequestV2 {
|
|
19
20
|
}
|
|
20
21
|
exports.NotificationQueueMessageRequestV2 = NotificationQueueMessageRequestV2;
|
|
@@ -77,6 +78,15 @@ __decorate([
|
|
|
77
78
|
(0, class_validator_1.IsString)(),
|
|
78
79
|
__metadata("design:type", String)
|
|
79
80
|
], NotificationQueueMessageRequestV2.prototype, "referenceMessageId", void 0);
|
|
81
|
+
__decorate([
|
|
82
|
+
(0, class_transformer_1.Expose)(),
|
|
83
|
+
(0, class_validator_1.IsOptional)(),
|
|
84
|
+
(0, class_validator_1.IsString)(),
|
|
85
|
+
(0, class_validator_1.IsNotEmpty)(),
|
|
86
|
+
(0, class_validator_1.MaxLength)(MessageIdempotencyLimits_1.MESSAGE_IDEMPOTENCY_KEY_MAX_LENGTH),
|
|
87
|
+
(0, class_validator_1.Matches)(/^[^#]+$/, { message: 'idempotencyKey no puede contener "#"' }),
|
|
88
|
+
__metadata("design:type", String)
|
|
89
|
+
], NotificationQueueMessageRequestV2.prototype, "idempotencyKey", void 0);
|
|
80
90
|
__decorate([
|
|
81
91
|
(0, class_transformer_1.Expose)(),
|
|
82
92
|
(0, class_validator_1.IsOptional)(),
|
|
@@ -41,3 +41,4 @@ __exportStar(require("./dtos/MdmNotifyItem"), exports);
|
|
|
41
41
|
__exportStar(require("./dtos/MdmNotifyRequest"), exports);
|
|
42
42
|
__exportStar(require("./dtos/MdmNotifyResponse"), exports);
|
|
43
43
|
__exportStar(require("./dtos/MdmNotifyBatchResponse"), exports);
|
|
44
|
+
__exportStar(require("./constants/MessageIdempotencyLimits"), exports);
|
package/package.json
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
import { IsEnum, IsNotEmpty, IsObject, IsOptional, IsString, Validate } from 'class-validator';
|
|
1
|
+
import { IsEnum, IsNotEmpty, IsObject, IsOptional, IsString, Matches, MaxLength, Validate } from 'class-validator';
|
|
2
2
|
import { Expose } from 'class-transformer';
|
|
3
3
|
import { DeliveryChannelExtendedEnum } from '../enums/DeliveryChannelExtendedEnum';
|
|
4
4
|
import { NotificationOriginEnum } from '../enums/NotificationOriginEnum';
|
|
5
5
|
import { IsStringValueRecord } from '../validators/IsStringValueRecord';
|
|
6
|
+
import { MESSAGE_IDEMPOTENCY_KEY_MAX_LENGTH } from '../constants/MessageIdempotencyLimits';
|
|
6
7
|
|
|
7
8
|
export class NotificationQueueMessageRequestV2 {
|
|
8
9
|
/** Tenant emisor del mensaje. Si se omite, messages-business asume FIADO. */
|
|
@@ -50,14 +51,29 @@ export class NotificationQueueMessageRequestV2 {
|
|
|
50
51
|
@Validate(IsStringValueRecord)
|
|
51
52
|
variables!: Record<string, string>;
|
|
52
53
|
|
|
54
|
+
/** Referencia de correlacion del productor. NO deduplica: para eso esta `idempotencyKey`. */
|
|
55
|
+
@Expose()
|
|
56
|
+
@IsOptional()
|
|
57
|
+
@IsString()
|
|
58
|
+
referenceMessageId?: string;
|
|
59
|
+
|
|
53
60
|
/**
|
|
54
|
-
*
|
|
55
|
-
*
|
|
61
|
+
* Llave de idempotencia, opcional y explicita. Cuando viaja, messages-business entrega UNA
|
|
62
|
+
* sola vez el trio (tenantId, idempotencyKey, channelType).
|
|
63
|
+
*
|
|
64
|
+
* Va aparte de `referenceMessageId` a proposito: esa referencia identifica la CORRIDA que
|
|
65
|
+
* produjo el mensaje, no al mensaje, asi que usarla para deduplicar aplastaria en uno todos
|
|
66
|
+
* los avisos de un mismo barrido. La llave tiene que distinguir al destinatario.
|
|
67
|
+
*
|
|
68
|
+
* Un `#` en el valor hace ambigua la llave: no se admite.
|
|
56
69
|
*/
|
|
57
70
|
@Expose()
|
|
58
71
|
@IsOptional()
|
|
59
72
|
@IsString()
|
|
60
|
-
|
|
73
|
+
@IsNotEmpty()
|
|
74
|
+
@MaxLength(MESSAGE_IDEMPOTENCY_KEY_MAX_LENGTH)
|
|
75
|
+
@Matches(/^[^#]+$/, { message: 'idempotencyKey no puede contener "#"' })
|
|
76
|
+
idempotencyKey?: string;
|
|
61
77
|
|
|
62
78
|
@Expose()
|
|
63
79
|
@IsOptional()
|