@fiado/type-kit 3.661.0 → 3.662.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.
@@ -4,6 +4,7 @@ import {
4
4
  EMAIL_PATTERN,
5
5
  HTTPS_URL_PATTERN,
6
6
  IMEI_PATTERN,
7
+ PHONE_E164_PATTERN,
7
8
  PHONE_MX_ACCEPTED_PATTERN,
8
9
  PHONE_MX_PATTERN,
9
10
  RFC_PATTERN,
@@ -34,6 +35,14 @@ describe('InputPatterns', () => {
34
35
  );
35
36
  });
36
37
 
38
+ describe('PHONE_E164_PATTERN (celular guardado)', () => {
39
+ it('acepta +52 con 10 dígitos', () => expect(PHONE_E164_PATTERN.test('+525512345678')).toBe(true));
40
+ it.each(['5512345678', '525512345678', '+15512345678', '+52551234567', '+5255123456789', '+52 5512345678', ''])(
41
+ 'rechaza %s',
42
+ (v) => expect(PHONE_E164_PATTERN.test(v)).toBe(false),
43
+ );
44
+ });
45
+
37
46
  describe('EMAIL_PATTERN', () => {
38
47
  it.each(['ana@somosfiado.com', 'a.b+tag@sub.dominio.mx'])('acepta %s', (v) => expect(EMAIL_PATTERN.test(v)).toBe(true));
39
48
  it.each(['ana', 'ana@', '@fiado.com', 'ana@fiado', 'ana @fiado.com', 'ana@@fiado.com', ''])(
@@ -0,0 +1,29 @@
1
+ import 'reflect-metadata';
2
+ import { plainToInstance, type ClassConstructor } from 'class-transformer';
3
+ import { validateSync } from 'class-validator';
4
+ import { EvaluateSciRequest } from '../../../src/loanScoring/dtos/requests/EvaluateSciRequest';
5
+ import { UpsertCustomerFromKycRequest } from '../../../src/retailCustomer/dtos/requests/UpsertCustomerFromKycRequest';
6
+ import { LinkRetailUserWalletRequest } from '../../../src/retailOrg/dtos/requests/LinkRetailUserWalletRequest';
7
+ import { LookupRetailUserWalletRequest } from '../../../src/retailOrg/dtos/requests/LookupRetailUserWalletRequest';
8
+ import { StartSessionRequest } from '../../../src/retailWizard/dtos/requests/StartSessionRequest';
9
+
10
+ const failsOn = (cls: ClassConstructor<object>, field: string, value: unknown): boolean =>
11
+ validateSync(plainToInstance(cls, { [field]: value })).some((error) => error.property === field);
12
+
13
+ const dtos: Array<[string, ClassConstructor<object>, string]> = [
14
+ ['StartSessionRequest', StartSessionRequest, 'phone'],
15
+ ['UpsertCustomerFromKycRequest', UpsertCustomerFromKycRequest, 'phone'],
16
+ ['EvaluateSciRequest', EvaluateSciRequest, 'cellphone'],
17
+ ['LinkRetailUserWalletRequest', LinkRetailUserWalletRequest, 'phone'],
18
+ ['LookupRetailUserWalletRequest', LookupRetailUserWalletRequest, 'phone'],
19
+ ];
20
+
21
+ describe.each(dtos)('%s en la transición a E.164', (_name, cls, field) => {
22
+ it.each(['5512345678', '+525512345678'])('acepta %s', (value) => {
23
+ expect(failsOn(cls, field, value)).toBe(false);
24
+ });
25
+
26
+ it.each(['+15512345678', '525512345678', '551234567', '+52551234567'])('rechaza %s', (value) => {
27
+ expect(failsOn(cls, field, value)).toBe(true);
28
+ });
29
+ });
@@ -30,8 +30,8 @@ describe('EvaluateSciRequest', () => {
30
30
  expect(await errorProperties({ ...BODY, curp: 'XOAC900101HDFRRL05' })).toEqual([]);
31
31
  });
32
32
 
33
- it('rechaza celular con +52 o separadores, y borrowerId que no es ULID (L-177)', async () => {
34
- const body = { ...BODY, cellphone: '+525512345678', borrowerId: 'SMOKE-B-LSB' };
33
+ it('rechaza celular con otra lada o separadores, y borrowerId que no es ULID (L-177)', async () => {
34
+ const body = { ...BODY, cellphone: '+15512345678', borrowerId: 'SMOKE-B-LSB' };
35
35
  expect(await errorProperties(body)).toEqual(['borrowerId', 'cellphone']);
36
36
  expect(await errorProperties({ ...BODY, cellphone: '55 1234 5678' })).toEqual(['cellphone']);
37
37
  });
@@ -3,6 +3,9 @@ export declare const PHONE_MX_PATTERN: RegExp;
3
3
  /** Teléfono MX en el backend: 10 dígitos, opcionalmente con `+52` para clientes que ya lo mandan. */
4
4
  export declare const PHONE_MX_ACCEPTED_PATTERN: RegExp;
5
5
  export declare const PHONE_MX_MESSAGE = "El tel\u00E9fono debe tener 10 d\u00EDgitos";
6
+ /** Celular guardado en todo SureKeep: `+52` y 10 dígitos. */
7
+ export declare const PHONE_E164_PATTERN: RegExp;
8
+ export declare const PHONE_E164_MESSAGE = "El tel\u00E9fono debe tener el formato +52 y 10 d\u00EDgitos";
6
9
  /** Correo pragmático: algo@dominio.tld, sin espacios. */
7
10
  export declare const EMAIL_PATTERN: RegExp;
8
11
  export declare const EMAIL_MAX_LENGTH = 254;
@@ -1,11 +1,14 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.HTTPS_URL_MESSAGE = exports.HTTPS_URL_PATTERN = exports.IMEI_MESSAGE = exports.IMEI_PATTERN = exports.SKU_MESSAGE = exports.SKU_MAX_LENGTH = exports.SKU_PATTERN = exports.ZIP_CODE_MX_MESSAGE = exports.ZIP_CODE_MX_PATTERN = exports.RFC_MESSAGE = exports.RFC_PATTERN = exports.EMAIL_MESSAGE = exports.EMAIL_MAX_LENGTH = exports.EMAIL_PATTERN = exports.PHONE_MX_MESSAGE = exports.PHONE_MX_ACCEPTED_PATTERN = exports.PHONE_MX_PATTERN = void 0;
3
+ exports.HTTPS_URL_MESSAGE = exports.HTTPS_URL_PATTERN = exports.IMEI_MESSAGE = exports.IMEI_PATTERN = exports.SKU_MESSAGE = exports.SKU_MAX_LENGTH = exports.SKU_PATTERN = exports.ZIP_CODE_MX_MESSAGE = exports.ZIP_CODE_MX_PATTERN = exports.RFC_MESSAGE = exports.RFC_PATTERN = exports.EMAIL_MESSAGE = exports.EMAIL_MAX_LENGTH = exports.EMAIL_PATTERN = exports.PHONE_E164_MESSAGE = exports.PHONE_E164_PATTERN = exports.PHONE_MX_MESSAGE = exports.PHONE_MX_ACCEPTED_PATTERN = exports.PHONE_MX_PATTERN = void 0;
4
4
  /** Teléfono MX tal como se teclea en la UI: exactamente 10 dígitos. */
5
5
  exports.PHONE_MX_PATTERN = /^\d{10}$/;
6
6
  /** Teléfono MX en el backend: 10 dígitos, opcionalmente con `+52` para clientes que ya lo mandan. */
7
7
  exports.PHONE_MX_ACCEPTED_PATTERN = /^(?:\+52)?\d{10}$/;
8
8
  exports.PHONE_MX_MESSAGE = 'El teléfono debe tener 10 dígitos';
9
+ /** Celular guardado en todo SureKeep: `+52` y 10 dígitos. */
10
+ exports.PHONE_E164_PATTERN = /^\+52\d{10}$/;
11
+ exports.PHONE_E164_MESSAGE = 'El teléfono debe tener el formato +52 y 10 dígitos';
9
12
  /** Correo pragmático: algo@dominio.tld, sin espacios. */
10
13
  exports.EMAIL_PATTERN = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
11
14
  exports.EMAIL_MAX_LENGTH = 254;
@@ -26,7 +26,7 @@ export declare class EvaluateSciRequest {
26
26
  * tumbaría la evaluación del wizard. El formato lo revisa loan-scoring antes de consultar (L-177, A).
27
27
  */
28
28
  curp: string;
29
- /** Celular del solicitante: 10 dígitos, sin `+52` (requerido por Modelias). */
29
+ /** Celular del solicitante: 10 dígitos, con o sin `+52`; loan-scoring lo manda a 10 a Modelias. */
30
30
  cellphone: string;
31
31
  email?: string;
32
32
  /**
@@ -55,7 +55,7 @@ __decorate([
55
55
  __decorate([
56
56
  (0, class_validator_1.IsString)(),
57
57
  (0, class_validator_1.IsNotEmpty)(),
58
- (0, class_validator_1.Matches)(InputPatterns_1.PHONE_MX_PATTERN, { message: 'cellphone debe tener 10 dígitos' }),
58
+ (0, class_validator_1.Matches)(InputPatterns_1.PHONE_MX_ACCEPTED_PATTERN, { message: 'cellphone debe tener 10 dígitos, con o sin +52' }),
59
59
  __metadata("design:type", String)
60
60
  ], EvaluateSciRequest.prototype, "cellphone", void 0);
61
61
  __decorate([
@@ -12,6 +12,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
12
12
  exports.UpsertCustomerFromKycRequest = void 0;
13
13
  const class_transformer_1 = require("class-transformer");
14
14
  const class_validator_1 = require("class-validator");
15
+ const InputPatterns_1 = require("../../../common/constants/InputPatterns");
15
16
  const regex_1 = require("../../../helpers/constans/regex");
16
17
  const RetailAddress_1 = require("../RetailAddress");
17
18
  const KycMethodEnum_1 = require("../../enums/KycMethodEnum");
@@ -56,7 +57,7 @@ __decorate([
56
57
  (0, class_transformer_1.Expose)(),
57
58
  (0, class_transformer_1.Transform)(({ value }) => (typeof value === 'string' ? value.replace(/[\s-]/g, '') : value)),
58
59
  (0, class_validator_1.IsString)(),
59
- (0, class_validator_1.Matches)(regex_1.regexPhoneMx, { message: 'phone debe ser 10 dígitos MX' }),
60
+ (0, class_validator_1.Matches)(InputPatterns_1.PHONE_MX_ACCEPTED_PATTERN, { message: 'phone debe ser 10 dígitos MX, con o sin +52' }),
60
61
  __metadata("design:type", String)
61
62
  ], UpsertCustomerFromKycRequest.prototype, "phone", void 0);
62
63
  __decorate([
@@ -12,6 +12,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
12
12
  exports.LinkRetailUserWalletRequest = void 0;
13
13
  const class_transformer_1 = require("class-transformer");
14
14
  const class_validator_1 = require("class-validator");
15
+ const InputPatterns_1 = require("../../../common/constants/InputPatterns");
15
16
  const IsSingleWalletKeyConstraint_1 = require("../../validators/IsSingleWalletKeyConstraint");
16
17
  /**
17
18
  * Body de `PUT /retailers/{retailerId}/users/{retailUserId}/wallet`: vincula la wallet PCF del
@@ -32,6 +33,6 @@ __decorate([
32
33
  (0, class_transformer_1.Expose)(),
33
34
  (0, class_validator_1.IsOptional)(),
34
35
  (0, class_validator_1.IsString)({ message: 'phone debe ser texto' }),
35
- (0, class_validator_1.Matches)(/^(\+52)?\d{10}$/, { message: 'phone debe tener 10 dígitos, con o sin +52' }),
36
+ (0, class_validator_1.Matches)(InputPatterns_1.PHONE_MX_ACCEPTED_PATTERN, { message: 'phone debe tener 10 dígitos, con o sin +52' }),
36
37
  __metadata("design:type", String)
37
38
  ], LinkRetailUserWalletRequest.prototype, "phone", void 0);
@@ -12,6 +12,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
12
12
  exports.LookupRetailUserWalletRequest = void 0;
13
13
  const class_transformer_1 = require("class-transformer");
14
14
  const class_validator_1 = require("class-validator");
15
+ const InputPatterns_1 = require("../../../common/constants/InputPatterns");
15
16
  const IsSingleWalletKeyConstraint_1 = require("../../validators/IsSingleWalletKeyConstraint");
16
17
  /**
17
18
  * Body de `POST /retailers/{retailerId}/users/wallet-lookup`: busca una wallet PCF por CLABE o por
@@ -32,6 +33,6 @@ __decorate([
32
33
  (0, class_transformer_1.Expose)(),
33
34
  (0, class_validator_1.IsOptional)(),
34
35
  (0, class_validator_1.IsString)({ message: 'phone debe ser texto' }),
35
- (0, class_validator_1.Matches)(/^(\+52)?\d{10}$/, { message: 'phone debe tener 10 dígitos, con o sin +52' }),
36
+ (0, class_validator_1.Matches)(InputPatterns_1.PHONE_MX_ACCEPTED_PATTERN, { message: 'phone debe tener 10 dígitos, con o sin +52' }),
36
37
  __metadata("design:type", String)
37
38
  ], LookupRetailUserWalletRequest.prototype, "phone", void 0);
@@ -12,7 +12,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
12
12
  exports.StartSessionRequest = void 0;
13
13
  const class_transformer_1 = require("class-transformer");
14
14
  const class_validator_1 = require("class-validator");
15
- const regex_1 = require("../../../helpers/constans/regex");
15
+ const InputPatterns_1 = require("../../../common/constants/InputPatterns");
16
16
  /**
17
17
  * POST /wizard/sessions — arranca (o reanuda) la saga del wizard para un teléfono.
18
18
  * `retailerId`/`storeId`/`sellerRetailUserId` NO viajan en el body: se derivan del JWT del vendedor.
@@ -24,7 +24,7 @@ exports.StartSessionRequest = StartSessionRequest;
24
24
  __decorate([
25
25
  (0, class_transformer_1.Expose)(),
26
26
  (0, class_validator_1.IsString)(),
27
- (0, class_validator_1.Matches)(regex_1.regexPhoneMx, { message: 'phone debe ser un teléfono MX de 10 dígitos' }),
27
+ (0, class_validator_1.Matches)(InputPatterns_1.PHONE_MX_ACCEPTED_PATTERN, { message: 'phone debe ser un teléfono MX de 10 dígitos, con o sin +52' }),
28
28
  __metadata("design:type", String)
29
29
  ], StartSessionRequest.prototype, "phone", void 0);
30
30
  __decorate([
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fiado/type-kit",
3
- "version": "3.661.0",
3
+ "version": "3.662.0",
4
4
  "description": "",
5
5
  "main": "bin/index.js",
6
6
  "types": "bin/index.d.ts",
@@ -5,6 +5,10 @@ export const PHONE_MX_PATTERN = /^\d{10}$/;
5
5
  export const PHONE_MX_ACCEPTED_PATTERN = /^(?:\+52)?\d{10}$/;
6
6
  export const PHONE_MX_MESSAGE = 'El teléfono debe tener 10 dígitos';
7
7
 
8
+ /** Celular guardado en todo SureKeep: `+52` y 10 dígitos. */
9
+ export const PHONE_E164_PATTERN = /^\+52\d{10}$/;
10
+ export const PHONE_E164_MESSAGE = 'El teléfono debe tener el formato +52 y 10 dígitos';
11
+
8
12
  /** Correo pragmático: algo@dominio.tld, sin espacios. */
9
13
  export const EMAIL_PATTERN = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
10
14
  export const EMAIL_MAX_LENGTH = 254;
@@ -1,6 +1,6 @@
1
1
  import { Type } from 'class-transformer';
2
2
  import { IsBoolean, IsEmail, IsNotEmpty, IsOptional, IsString, Matches, MaxLength, ValidateNested } from 'class-validator';
3
- import { PHONE_MX_PATTERN } from '../../../common/constants/InputPatterns';
3
+ import { PHONE_MX_ACCEPTED_PATTERN } from '../../../common/constants/InputPatterns';
4
4
  import { CREDIT_ID_PATTERN } from '../../../common/constants/CreditIdPattern';
5
5
  import { SciInternalHistoryInput } from './SciInternalHistoryInput';
6
6
 
@@ -49,10 +49,10 @@ export class EvaluateSciRequest {
49
49
  @MaxLength(64)
50
50
  curp!: string;
51
51
 
52
- /** Celular del solicitante: 10 dígitos, sin `+52` (requerido por Modelias). */
52
+ /** Celular del solicitante: 10 dígitos, con o sin `+52`; loan-scoring lo manda a 10 a Modelias. */
53
53
  @IsString()
54
54
  @IsNotEmpty()
55
- @Matches(PHONE_MX_PATTERN, { message: 'cellphone debe tener 10 dígitos' })
55
+ @Matches(PHONE_MX_ACCEPTED_PATTERN, { message: 'cellphone debe tener 10 dígitos, con o sin +52' })
56
56
  cellphone!: string;
57
57
 
58
58
  @IsOptional()
@@ -10,7 +10,8 @@ import {
10
10
  Matches,
11
11
  ValidateNested,
12
12
  } from 'class-validator';
13
- import { regexCurp, regexIso8601Date, regexPhoneMx } from '../../../helpers/constans/regex';
13
+ import { PHONE_MX_ACCEPTED_PATTERN } from '../../../common/constants/InputPatterns';
14
+ import { regexCurp, regexIso8601Date } from '../../../helpers/constans/regex';
14
15
  import { RetailAddress } from '../RetailAddress';
15
16
  import { KycMethodEnum } from '../../enums/KycMethodEnum';
16
17
  import { KycModalityEnum } from '../../enums/KycModalityEnum';
@@ -53,7 +54,7 @@ export class UpsertCustomerFromKycRequest {
53
54
  @Expose()
54
55
  @Transform(({ value }) => (typeof value === 'string' ? value.replace(/[\s-]/g, '') : value))
55
56
  @IsString()
56
- @Matches(regexPhoneMx, { message: 'phone debe ser 10 dígitos MX' })
57
+ @Matches(PHONE_MX_ACCEPTED_PATTERN, { message: 'phone debe ser 10 dígitos MX, con o sin +52' })
57
58
  phone!: string;
58
59
 
59
60
  // Normalización en el boundary: el CURP se uppercasea para no evadir la unicidad transaccional
@@ -1,5 +1,6 @@
1
1
  import { Expose } from 'class-transformer';
2
2
  import { IsOptional, IsString, Matches, Validate, ValidateIf } from 'class-validator';
3
+ import { PHONE_MX_ACCEPTED_PATTERN } from '../../../common/constants/InputPatterns';
3
4
  import { IsSingleWalletKeyConstraint } from '../../validators/IsSingleWalletKeyConstraint';
4
5
 
5
6
  /**
@@ -19,6 +20,6 @@ export class LinkRetailUserWalletRequest {
19
20
  @Expose()
20
21
  @IsOptional()
21
22
  @IsString({ message: 'phone debe ser texto' })
22
- @Matches(/^(\+52)?\d{10}$/, { message: 'phone debe tener 10 dígitos, con o sin +52' })
23
+ @Matches(PHONE_MX_ACCEPTED_PATTERN, { message: 'phone debe tener 10 dígitos, con o sin +52' })
23
24
  phone?: string | null;
24
25
  }
@@ -1,5 +1,6 @@
1
1
  import { Expose } from 'class-transformer';
2
2
  import { IsOptional, IsString, Matches, Validate, ValidateIf } from 'class-validator';
3
+ import { PHONE_MX_ACCEPTED_PATTERN } from '../../../common/constants/InputPatterns';
3
4
  import { IsSingleWalletKeyConstraint } from '../../validators/IsSingleWalletKeyConstraint';
4
5
 
5
6
  /**
@@ -19,6 +20,6 @@ export class LookupRetailUserWalletRequest {
19
20
  @Expose()
20
21
  @IsOptional()
21
22
  @IsString({ message: 'phone debe ser texto' })
22
- @Matches(/^(\+52)?\d{10}$/, { message: 'phone debe tener 10 dígitos, con o sin +52' })
23
+ @Matches(PHONE_MX_ACCEPTED_PATTERN, { message: 'phone debe tener 10 dígitos, con o sin +52' })
23
24
  phone?: string | null;
24
25
  }
@@ -1,6 +1,6 @@
1
1
  import { Expose } from 'class-transformer';
2
2
  import { IsBoolean, IsOptional, IsString, Matches } from 'class-validator';
3
- import { regexPhoneMx } from '../../../helpers/constans/regex';
3
+ import { PHONE_MX_ACCEPTED_PATTERN } from '../../../common/constants/InputPatterns';
4
4
 
5
5
  /**
6
6
  * POST /wizard/sessions — arranca (o reanuda) la saga del wizard para un teléfono.
@@ -10,7 +10,7 @@ import { regexPhoneMx } from '../../../helpers/constans/regex';
10
10
  export class StartSessionRequest {
11
11
  @Expose()
12
12
  @IsString()
13
- @Matches(regexPhoneMx, { message: 'phone debe ser un teléfono MX de 10 dígitos' })
13
+ @Matches(PHONE_MX_ACCEPTED_PATTERN, { message: 'phone debe ser un teléfono MX de 10 dígitos, con o sin +52' })
14
14
  phone!: string;
15
15
 
16
16
  /** Prospecto a reanudar (opcional): si viene, la sesión se vincula al prospecto. */