Revisión general
This commit is contained in:
parent
2df2ce7083
commit
7470b15cfe
@ -2,6 +2,7 @@ import { logger } from "@/lib/logger";
|
|||||||
import { DateTime } from "luxon";
|
import { DateTime } from "luxon";
|
||||||
import http from "node:http";
|
import http from "node:http";
|
||||||
import os from "node:os";
|
import os from "node:os";
|
||||||
|
import * as z from "zod/v4";
|
||||||
import { createApp } from "./app";
|
import { createApp } from "./app";
|
||||||
import { ENV } from "./config";
|
import { ENV } from "./config";
|
||||||
import { tryConnectToDatabase } from "./config/database";
|
import { tryConnectToDatabase } from "./config/database";
|
||||||
@ -12,6 +13,8 @@ import { registerModules } from "./register-modules";
|
|||||||
|
|
||||||
const API_BASE_PATH = "/api/v1";
|
const API_BASE_PATH = "/api/v1";
|
||||||
|
|
||||||
|
z.config(z.locales.es());
|
||||||
|
|
||||||
// Guardamos información del estado del servidor
|
// Guardamos información del estado del servidor
|
||||||
export const currentState = {
|
export const currentState = {
|
||||||
launchedAt: DateTime.now(),
|
launchedAt: DateTime.now(),
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
import { DomainError } from "./domain-error";
|
import { DomainError } from "@repo/rdx-ddd";
|
||||||
|
|
||||||
export class DuplicateEntityError extends DomainError {
|
export class DuplicateEntityError extends DomainError {
|
||||||
constructor(entity: string, field: string, value: string, options?: ErrorOptions) {
|
constructor(entity: string, field: string, value: string, options?: ErrorOptions) {
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
import { DomainError } from "./domain-error";
|
import { DomainError } from "@repo/rdx-ddd";
|
||||||
|
|
||||||
export class EntityNotFoundError extends DomainError {
|
export class EntityNotFoundError extends DomainError {
|
||||||
constructor(entity: string, field: string, value: any, options?: ErrorOptions) {
|
constructor(entity: string, field: string, value: any, options?: ErrorOptions) {
|
||||||
|
|||||||
@ -1,5 +1,2 @@
|
|||||||
export * from "./domain-error";
|
|
||||||
export * from "./domain-validation-error";
|
|
||||||
export * from "./duplicate-entity-error";
|
export * from "./duplicate-entity-error";
|
||||||
export * from "./entity-not-found-error";
|
export * from "./entity-not-found-error";
|
||||||
export * from "./validation-error-collection";
|
|
||||||
|
|||||||
@ -1 +1 @@
|
|||||||
export * from "./extract-or-push-error";
|
|
||||||
|
|||||||
@ -78,7 +78,7 @@ export abstract class TransactionManager implements ITransactionManager {
|
|||||||
await this.rollback();
|
await this.rollback();
|
||||||
const error = err as Error;
|
const error = err as Error;
|
||||||
this.logger.error(`❌ Transaction rolled back due to error: ${error.message}`, {
|
this.logger.error(`❌ Transaction rolled back due to error: ${error.message}`, {
|
||||||
stack: error.stack,
|
//stack: error.stack,
|
||||||
label: "TransactionManager.start",
|
label: "TransactionManager.start",
|
||||||
});
|
});
|
||||||
throw error;
|
throw error;
|
||||||
|
|||||||
@ -13,13 +13,16 @@
|
|||||||
|
|
||||||
import {
|
import {
|
||||||
DomainValidationError,
|
DomainValidationError,
|
||||||
DuplicateEntityError,
|
|
||||||
EntityNotFoundError,
|
|
||||||
ValidationErrorCollection,
|
ValidationErrorCollection,
|
||||||
isDomainValidationError,
|
isDomainValidationError,
|
||||||
|
isValidationErrorCollection,
|
||||||
|
} from "@repo/rdx-ddd";
|
||||||
|
|
||||||
|
import {
|
||||||
|
DuplicateEntityError,
|
||||||
|
EntityNotFoundError,
|
||||||
isDuplicateEntityError,
|
isDuplicateEntityError,
|
||||||
isEntityNotFoundError,
|
isEntityNotFoundError,
|
||||||
isValidationErrorCollection,
|
|
||||||
} from "../../domain";
|
} from "../../domain";
|
||||||
import { isInfrastructureRepositoryError, isInfrastructureUnavailableError } from "../errors";
|
import { isInfrastructureRepositoryError, isInfrastructureUnavailableError } from "../errors";
|
||||||
import {
|
import {
|
||||||
|
|||||||
@ -1,3 +1,4 @@
|
|||||||
|
import { DomainValidationError, ValidationErrorCollection } from "@repo/rdx-ddd";
|
||||||
import {
|
import {
|
||||||
ConnectionError,
|
ConnectionError,
|
||||||
DatabaseError,
|
DatabaseError,
|
||||||
@ -5,12 +6,7 @@ import {
|
|||||||
ValidationError as SequelizeValidationError,
|
ValidationError as SequelizeValidationError,
|
||||||
UniqueConstraintError,
|
UniqueConstraintError,
|
||||||
} from "sequelize";
|
} from "sequelize";
|
||||||
import {
|
import { DuplicateEntityError, EntityNotFoundError } from "../../domain";
|
||||||
DomainValidationError,
|
|
||||||
DuplicateEntityError,
|
|
||||||
EntityNotFoundError,
|
|
||||||
ValidationErrorCollection,
|
|
||||||
} from "../../domain";
|
|
||||||
import { InfrastructureRepositoryError } from "../errors/infrastructure-repository-error";
|
import { InfrastructureRepositoryError } from "../errors/infrastructure-repository-error";
|
||||||
import { InfrastructureUnavailableError } from "../errors/infrastructure-unavailable-error";
|
import { InfrastructureUnavailableError } from "../errors/infrastructure-unavailable-error";
|
||||||
|
|
||||||
|
|||||||
@ -69,7 +69,7 @@ export class SequelizeTransactionManager extends TransactionManager {
|
|||||||
} catch (err) {
|
} catch (err) {
|
||||||
const error = err as Error;
|
const error = err as Error;
|
||||||
this.logger.error(`❌ Transaction rolled back due to error: ${error.message}`, {
|
this.logger.error(`❌ Transaction rolled back due to error: ${error.message}`, {
|
||||||
stack: error.stack,
|
//stack: error.stack,
|
||||||
label: "SequelizeTransactionManager.complete",
|
label: "SequelizeTransactionManager.complete",
|
||||||
});
|
});
|
||||||
throw error;
|
throw error;
|
||||||
|
|||||||
@ -28,6 +28,6 @@
|
|||||||
"noFallthroughCasesInSwitch": true,
|
"noFallthroughCasesInSwitch": true,
|
||||||
"noUncheckedSideEffectImports": true
|
"noUncheckedSideEffectImports": true
|
||||||
},
|
},
|
||||||
"include": ["src"],
|
"include": ["src", "../../packages/rdx-ddd/src/helpers/extract-or-push-error.ts"],
|
||||||
"exclude": ["node_modules"]
|
"exclude": ["node_modules"]
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,45 +0,0 @@
|
|||||||
import { DomainValidationError, ValidationErrorDetail } from "@erp/core/api";
|
|
||||||
import { Result } from "@repo/rdx-utils";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Extrae un valor de un Result si es válido.
|
|
||||||
* Si es un fallo, agrega un ValidationErrorDetail al array proporcionado.
|
|
||||||
* @param result - El resultado a evaluar.
|
|
||||||
* @param path - La ruta del error para el detalle de validación.
|
|
||||||
* @param errors - El array donde se agregarán los errores de validación.
|
|
||||||
* @returns El valor extraído si el resultado es exitoso, o undefined si es un fallo.
|
|
||||||
* @template T - El tipo de dato esperado en el resultado exitoso.
|
|
||||||
* @throws {Error} Si el resultado es un fallo y no es una instancia de DomainValidationError.
|
|
||||||
* @example
|
|
||||||
* const result = Result.ok(42);
|
|
||||||
* const value = extractOrPushError(result, 'some.path', []);
|
|
||||||
* console.log(value); // 42
|
|
||||||
* const errorResult = Result.fail(new Error('Something went wrong'));
|
|
||||||
* const value = extractOrPushError(errorResult, 'some.path', []);
|
|
||||||
* console.log(value); // undefined
|
|
||||||
* // errors will contain [{ path: 'some.path', message: 'Something went wrong' }]
|
|
||||||
*
|
|
||||||
* @see Result
|
|
||||||
* @see DomainValidationError
|
|
||||||
* @see ValidationErrorDetail
|
|
||||||
|
|
||||||
*/
|
|
||||||
export function extractOrPushError<T>(
|
|
||||||
result: Result<T, Error>,
|
|
||||||
path: string,
|
|
||||||
errors: ValidationErrorDetail[]
|
|
||||||
): T | undefined {
|
|
||||||
if (result.isFailure) {
|
|
||||||
const error = result.error;
|
|
||||||
|
|
||||||
if (error instanceof DomainValidationError) {
|
|
||||||
errors.push({ path, message: error.detail });
|
|
||||||
} else {
|
|
||||||
errors.push({ path, message: error.message });
|
|
||||||
}
|
|
||||||
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
|
|
||||||
return result.data;
|
|
||||||
}
|
|
||||||
@ -1,10 +1,8 @@
|
|||||||
import { ValidationErrorCollection, ValidationErrorDetail } from "@erp/core/api";
|
import { ValidationErrorCollection, ValidationErrorDetail } from "@repo/rdx-ddd";
|
||||||
import { CreateCustomerInvoiceCommandDTO } from "@erp/customer-invoices/common/dto";
|
|
||||||
import { Result } from "@repo/rdx-utils";
|
import { Result } from "@repo/rdx-utils";
|
||||||
import {
|
import {
|
||||||
CustomerInvoiceItem,
|
CustomerInvoiceItem,
|
||||||
CustomerInvoiceItemDescription,
|
CustomerInvoiceItemDescription,
|
||||||
CustomerInvoiceItemQuantity,
|
|
||||||
ItemAmount,
|
ItemAmount,
|
||||||
ItemDiscount,
|
ItemDiscount,
|
||||||
} from "../../domain";
|
} from "../../domain";
|
||||||
|
|||||||
@ -1,19 +1,16 @@
|
|||||||
import { JsonTaxCatalogProvider } from "@erp/core";
|
import { JsonTaxCatalogProvider } from "@erp/core";
|
||||||
import {
|
import { Tax, Taxes } from "@erp/core/api";
|
||||||
DomainError,
|
|
||||||
Tax,
|
|
||||||
Taxes,
|
|
||||||
ValidationErrorCollection,
|
|
||||||
ValidationErrorDetail,
|
|
||||||
extractOrPushError,
|
|
||||||
} from "@erp/core/api";
|
|
||||||
import {
|
import {
|
||||||
CurrencyCode,
|
CurrencyCode,
|
||||||
|
DomainError,
|
||||||
LanguageCode,
|
LanguageCode,
|
||||||
Percentage,
|
Percentage,
|
||||||
TextValue,
|
TextValue,
|
||||||
UniqueID,
|
UniqueID,
|
||||||
UtcDate,
|
UtcDate,
|
||||||
|
ValidationErrorCollection,
|
||||||
|
ValidationErrorDetail,
|
||||||
|
extractOrPushError,
|
||||||
maybeFromNullableVO,
|
maybeFromNullableVO,
|
||||||
} from "@repo/rdx-ddd";
|
} from "@repo/rdx-ddd";
|
||||||
import { Result } from "@repo/rdx-utils";
|
import { Result } from "@repo/rdx-utils";
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
// Ejemplo: regla específica para Billing → InvoiceIdAlreadyExistsError
|
// Ejemplo: regla específica para Billing → InvoiceIdAlreadyExistsError
|
||||||
// (si defines un error más ubicuo dentro del BC con su propia clase)
|
// (si defines un error más ubicuo dentro del BC con su propia clase)
|
||||||
|
|
||||||
import { DomainError } from "@erp/core/api";
|
import { DomainError } from "@repo/rdx-ddd";
|
||||||
|
|
||||||
// Suponemos que existe esta clase en tu dominio de Billing:
|
// Suponemos que existe esta clase en tu dominio de Billing:
|
||||||
export class CustomerInvoiceIdAlreadyExistsError extends DomainError {
|
export class CustomerInvoiceIdAlreadyExistsError extends DomainError {
|
||||||
|
|||||||
@ -1,12 +1,11 @@
|
|||||||
|
import { ISequelizeDomainMapper, MapperParamsType, SequelizeDomainMapper } from "@erp/core/api";
|
||||||
import {
|
import {
|
||||||
ISequelizeDomainMapper,
|
UniqueID,
|
||||||
MapperParamsType,
|
|
||||||
SequelizeDomainMapper,
|
|
||||||
ValidationErrorCollection,
|
ValidationErrorCollection,
|
||||||
ValidationErrorDetail,
|
ValidationErrorDetail,
|
||||||
extractOrPushError,
|
extractOrPushError,
|
||||||
} from "@erp/core/api";
|
maybeFromNullableVO,
|
||||||
import { UniqueID, maybeFromNullableVO } from "@repo/rdx-ddd";
|
} from "@repo/rdx-ddd";
|
||||||
import { Result } from "@repo/rdx-utils";
|
import { Result } from "@repo/rdx-utils";
|
||||||
import { InferCreationAttributes } from "sequelize";
|
import { InferCreationAttributes } from "sequelize";
|
||||||
import {
|
import {
|
||||||
|
|||||||
@ -1,11 +1,4 @@
|
|||||||
import {
|
import { ISequelizeDomainMapper, MapperParamsType, SequelizeDomainMapper } from "@erp/core/api";
|
||||||
ISequelizeDomainMapper,
|
|
||||||
MapperParamsType,
|
|
||||||
SequelizeDomainMapper,
|
|
||||||
ValidationErrorCollection,
|
|
||||||
ValidationErrorDetail,
|
|
||||||
extractOrPushError,
|
|
||||||
} from "@erp/core/api";
|
|
||||||
import {
|
import {
|
||||||
CurrencyCode,
|
CurrencyCode,
|
||||||
LanguageCode,
|
LanguageCode,
|
||||||
@ -13,6 +6,9 @@ import {
|
|||||||
TextValue,
|
TextValue,
|
||||||
UniqueID,
|
UniqueID,
|
||||||
UtcDate,
|
UtcDate,
|
||||||
|
ValidationErrorCollection,
|
||||||
|
ValidationErrorDetail,
|
||||||
|
extractOrPushError,
|
||||||
maybeFromNullableVO,
|
maybeFromNullableVO,
|
||||||
} from "@repo/rdx-ddd";
|
} from "@repo/rdx-ddd";
|
||||||
import { Maybe, Result } from "@repo/rdx-utils";
|
import { Maybe, Result } from "@repo/rdx-utils";
|
||||||
|
|||||||
@ -6,15 +6,13 @@ import {
|
|||||||
Province,
|
Province,
|
||||||
Street,
|
Street,
|
||||||
TINNumber,
|
TINNumber,
|
||||||
maybeFromNullableVO,
|
|
||||||
} from "@repo/rdx-ddd";
|
|
||||||
|
|
||||||
import {
|
|
||||||
MapperParamsType,
|
|
||||||
ValidationErrorCollection,
|
ValidationErrorCollection,
|
||||||
ValidationErrorDetail,
|
ValidationErrorDetail,
|
||||||
extractOrPushError,
|
extractOrPushError,
|
||||||
} from "@erp/core/api";
|
maybeFromNullableVO,
|
||||||
|
} from "@repo/rdx-ddd";
|
||||||
|
|
||||||
|
import { MapperParamsType } from "@erp/core/api";
|
||||||
import { Maybe, Result } from "@repo/rdx-utils";
|
import { Maybe, Result } from "@repo/rdx-utils";
|
||||||
import { CustomerInvoiceProps, InvoiceRecipient } from "../../../domain";
|
import { CustomerInvoiceProps, InvoiceRecipient } from "../../../domain";
|
||||||
import { CustomerInvoiceModel } from "../../sequelize";
|
import { CustomerInvoiceModel } from "../../sequelize";
|
||||||
|
|||||||
@ -1,12 +1,10 @@
|
|||||||
import { JsonTaxCatalogProvider } from "@erp/core";
|
import { JsonTaxCatalogProvider } from "@erp/core";
|
||||||
|
import { MapperParamsType, SequelizeDomainMapper, Tax } from "@erp/core/api";
|
||||||
import {
|
import {
|
||||||
MapperParamsType,
|
|
||||||
SequelizeDomainMapper,
|
|
||||||
Tax,
|
|
||||||
ValidationErrorCollection,
|
ValidationErrorCollection,
|
||||||
ValidationErrorDetail,
|
ValidationErrorDetail,
|
||||||
extractOrPushError,
|
extractOrPushError,
|
||||||
} from "@erp/core/api";
|
} from "@repo/rdx-ddd";
|
||||||
import { Result } from "@repo/rdx-utils";
|
import { Result } from "@repo/rdx-utils";
|
||||||
import { ItemTax } from "../../../domain";
|
import { ItemTax } from "../../../domain";
|
||||||
import {
|
import {
|
||||||
|
|||||||
@ -1,12 +1,11 @@
|
|||||||
import { JsonTaxCatalogProvider } from "@erp/core";
|
import { JsonTaxCatalogProvider } from "@erp/core";
|
||||||
|
import { MapperParamsType, SequelizeDomainMapper, Tax } from "@erp/core/api";
|
||||||
import {
|
import {
|
||||||
MapperParamsType,
|
|
||||||
SequelizeDomainMapper,
|
|
||||||
Tax,
|
|
||||||
ValidationErrorCollection,
|
ValidationErrorCollection,
|
||||||
ValidationErrorDetail,
|
ValidationErrorDetail,
|
||||||
extractOrPushError,
|
extractOrPushError,
|
||||||
} from "@erp/core/api";
|
} from "@repo/rdx-ddd";
|
||||||
|
|
||||||
import { Result } from "@repo/rdx-utils";
|
import { Result } from "@repo/rdx-utils";
|
||||||
import { CustomerInvoiceProps } from "../../../domain";
|
import { CustomerInvoiceProps } from "../../../domain";
|
||||||
import { InvoiceTax } from "../../../domain/entities/invoice-taxes";
|
import { InvoiceTax } from "../../../domain/entities/invoice-taxes";
|
||||||
|
|||||||
@ -1,11 +1,11 @@
|
|||||||
|
import { ISequelizeQueryMapper, MapperParamsType, SequelizeQueryMapper } from "@erp/core/api";
|
||||||
|
|
||||||
import {
|
import {
|
||||||
ISequelizeQueryMapper,
|
|
||||||
MapperParamsType,
|
|
||||||
SequelizeQueryMapper,
|
|
||||||
ValidationErrorCollection,
|
ValidationErrorCollection,
|
||||||
ValidationErrorDetail,
|
ValidationErrorDetail,
|
||||||
extractOrPushError,
|
extractOrPushError,
|
||||||
} from "@erp/core/api";
|
} from "@repo/rdx-ddd";
|
||||||
|
|
||||||
import {
|
import {
|
||||||
CurrencyCode,
|
CurrencyCode,
|
||||||
LanguageCode,
|
LanguageCode,
|
||||||
|
|||||||
@ -1,13 +1,8 @@
|
|||||||
import {
|
|
||||||
DomainError,
|
|
||||||
ValidationErrorCollection,
|
|
||||||
ValidationErrorDetail,
|
|
||||||
extractOrPushError,
|
|
||||||
} from "@erp/core/api";
|
|
||||||
import {
|
import {
|
||||||
City,
|
City,
|
||||||
Country,
|
Country,
|
||||||
CurrencyCode,
|
CurrencyCode,
|
||||||
|
DomainError,
|
||||||
EmailAddress,
|
EmailAddress,
|
||||||
LanguageCode,
|
LanguageCode,
|
||||||
Name,
|
Name,
|
||||||
@ -21,6 +16,9 @@ import {
|
|||||||
TextValue,
|
TextValue,
|
||||||
URLAddress,
|
URLAddress,
|
||||||
UniqueID,
|
UniqueID,
|
||||||
|
ValidationErrorCollection,
|
||||||
|
ValidationErrorDetail,
|
||||||
|
extractOrPushError,
|
||||||
maybeFromNullableVO,
|
maybeFromNullableVO,
|
||||||
} from "@repo/rdx-ddd";
|
} from "@repo/rdx-ddd";
|
||||||
import { Collection, Result, isNullishOrEmpty } from "@repo/rdx-utils";
|
import { Collection, Result, isNullishOrEmpty } from "@repo/rdx-utils";
|
||||||
|
|||||||
@ -1,9 +1,5 @@
|
|||||||
import {
|
import { DomainError, ValidationErrorCollection, ValidationErrorDetail } from "@repo/rdx-ddd";
|
||||||
DomainError,
|
|
||||||
ValidationErrorCollection,
|
|
||||||
ValidationErrorDetail,
|
|
||||||
extractOrPushError,
|
|
||||||
} from "@erp/core/api";
|
|
||||||
import {
|
import {
|
||||||
City,
|
City,
|
||||||
Country,
|
Country,
|
||||||
@ -23,8 +19,6 @@ import {
|
|||||||
maybeFromNullableVO,
|
maybeFromNullableVO,
|
||||||
} from "@repo/rdx-ddd";
|
} from "@repo/rdx-ddd";
|
||||||
import { Collection, Result, isNullishOrEmpty, toPatchField } from "@repo/rdx-utils";
|
import { Collection, Result, isNullishOrEmpty, toPatchField } from "@repo/rdx-utils";
|
||||||
import { UpdateCustomerRequestDTO } from "../../../common/dto";
|
|
||||||
import { CustomerPatchProps } from "../../domain";
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* mapDTOToUpdateCustomerPatchProps
|
* mapDTOToUpdateCustomerPatchProps
|
||||||
|
|||||||
@ -1,11 +1,6 @@
|
|||||||
import {
|
import { ValidationErrorCollection, ValidationErrorDetail } from "@repo/rdx-ddd";
|
||||||
ISequelizeDomainMapper,
|
|
||||||
MapperParamsType,
|
import { ISequelizeDomainMapper, MapperParamsType, SequelizeDomainMapper } from "@erp/core/api";
|
||||||
SequelizeDomainMapper,
|
|
||||||
ValidationErrorCollection,
|
|
||||||
ValidationErrorDetail,
|
|
||||||
extractOrPushError,
|
|
||||||
} from "@erp/core/api";
|
|
||||||
import {
|
import {
|
||||||
City,
|
City,
|
||||||
Country,
|
Country,
|
||||||
@ -23,6 +18,7 @@ import {
|
|||||||
TextValue,
|
TextValue,
|
||||||
URLAddress,
|
URLAddress,
|
||||||
UniqueID,
|
UniqueID,
|
||||||
|
extractOrPushError,
|
||||||
maybeFromNullableVO,
|
maybeFromNullableVO,
|
||||||
toNullable,
|
toNullable,
|
||||||
} from "@repo/rdx-ddd";
|
} from "@repo/rdx-ddd";
|
||||||
|
|||||||
@ -1,3 +1,5 @@
|
|||||||
|
import { ValidationErrorCollection, ValidationErrorDetail } from "@repo/rdx-ddd";
|
||||||
|
|
||||||
import {
|
import {
|
||||||
City,
|
City,
|
||||||
Country,
|
Country,
|
||||||
@ -14,17 +16,11 @@ import {
|
|||||||
TextValue,
|
TextValue,
|
||||||
URLAddress,
|
URLAddress,
|
||||||
UniqueID,
|
UniqueID,
|
||||||
|
extractOrPushError,
|
||||||
maybeFromNullableVO,
|
maybeFromNullableVO,
|
||||||
} from "@repo/rdx-ddd";
|
} from "@repo/rdx-ddd";
|
||||||
|
|
||||||
import {
|
import { ISequelizeQueryMapper, MapperParamsType, SequelizeQueryMapper } from "@erp/core/api";
|
||||||
ISequelizeQueryMapper,
|
|
||||||
MapperParamsType,
|
|
||||||
SequelizeQueryMapper,
|
|
||||||
ValidationErrorCollection,
|
|
||||||
ValidationErrorDetail,
|
|
||||||
extractOrPushError,
|
|
||||||
} from "@erp/core/api";
|
|
||||||
|
|
||||||
import { Maybe, Result } from "@repo/rdx-utils";
|
import { Maybe, Result } from "@repo/rdx-utils";
|
||||||
import { CustomerStatus } from "../../../domain";
|
import { CustomerStatus } from "../../../domain";
|
||||||
|
|||||||
@ -28,6 +28,6 @@
|
|||||||
"noFallthroughCasesInSwitch": true,
|
"noFallthroughCasesInSwitch": true,
|
||||||
"noUncheckedSideEffectImports": true
|
"noUncheckedSideEffectImports": true
|
||||||
},
|
},
|
||||||
"include": ["src", "../core/src/api/helpers/extract-or-push-error.ts"],
|
"include": ["src", "../../packages/rdx-ddd/src/helpers/extract-or-push-error.ts"],
|
||||||
"exclude": ["node_modules"]
|
"exclude": ["node_modules"]
|
||||||
}
|
}
|
||||||
|
|||||||
@ -35,12 +35,20 @@ export class DomainValidationError extends DomainError {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Constructores rápidos
|
// Constructores rápidos
|
||||||
static required(field: string, options?: ErrorOptions) {
|
static requiredValue(field: string, options?: ErrorOptions) {
|
||||||
return new DomainValidationError("REQUIRED", field, "cannot be empty", options);
|
return new DomainValidationError("REQUIRED_VALUE", field, "cannot be empty", options);
|
||||||
}
|
}
|
||||||
static invalidFormat(field: string, detail = "invalid format", options?: ErrorOptions) {
|
static invalidFormat(field: string, detail = "invalid format", options?: ErrorOptions) {
|
||||||
return new DomainValidationError("INVALID_FORMAT", field, detail, options);
|
return new DomainValidationError("INVALID_FORMAT", field, detail, options);
|
||||||
}
|
}
|
||||||
|
static invalidValue(
|
||||||
|
field: string,
|
||||||
|
value: unknown,
|
||||||
|
detail = "invalid value",
|
||||||
|
options?: ErrorOptions
|
||||||
|
) {
|
||||||
|
return new DomainValidationError("INVALID_VALUE", field, detail, { ...options, cause: value });
|
||||||
|
}
|
||||||
|
|
||||||
// Proyección útil para Problem+JSON o colecciones
|
// Proyección útil para Problem+JSON o colecciones
|
||||||
toDetail() {
|
toDetail() {
|
||||||
3
packages/rdx-ddd/src/errors/index.ts
Normal file
3
packages/rdx-ddd/src/errors/index.ts
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
export * from "./domain-error";
|
||||||
|
export * from "./domain-validation-error";
|
||||||
|
export * from "./validation-error-collection";
|
||||||
@ -18,8 +18,9 @@
|
|||||||
import { DomainError } from "./domain-error";
|
import { DomainError } from "./domain-error";
|
||||||
|
|
||||||
export interface ValidationErrorDetail {
|
export interface ValidationErrorDetail {
|
||||||
path: string; // ejemplo: "lines[1].unitPrice.amount"
|
path?: string; // ejemplo: "lines[1].unitPrice.amount"
|
||||||
message: string; // ejemplo: "Amount must be a positive number",
|
message: string; // ejemplo: "Amount must be a positive number",
|
||||||
|
value?: unknown; // valor inválido opcional
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1,5 +1,10 @@
|
|||||||
import { DomainValidationError, ValidationErrorDetail } from "@erp/core/api";
|
|
||||||
import { Result } from "@repo/rdx-utils";
|
import { Result } from "@repo/rdx-utils";
|
||||||
|
import {
|
||||||
|
DomainValidationError,
|
||||||
|
ValidationErrorDetail,
|
||||||
|
isDomainValidationError,
|
||||||
|
isValidationErrorCollection,
|
||||||
|
} from "../errors";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Extrae un valor de un Result si es válido.
|
* Extrae un valor de un Result si es válido.
|
||||||
@ -32,8 +37,11 @@ export function extractOrPushError<T>(
|
|||||||
if (result.isFailure) {
|
if (result.isFailure) {
|
||||||
const error = result.error;
|
const error = result.error;
|
||||||
|
|
||||||
if (error instanceof DomainValidationError) {
|
if (isValidationErrorCollection(error)) {
|
||||||
errors.push({ path, message: error.detail });
|
// Agrega todos los detalles de error al array proporcionado
|
||||||
|
errors.push(...error.details);
|
||||||
|
} else if (isDomainValidationError(error)) {
|
||||||
|
errors.push({ path, message: error.detail, value: error.cause?.toString() });
|
||||||
} else {
|
} else {
|
||||||
errors.push({ path, message: error.message });
|
errors.push({ path, message: error.message });
|
||||||
}
|
}
|
||||||
@ -1 +1,3 @@
|
|||||||
|
export * from "./extract-or-push-error";
|
||||||
export * from "./normalizers";
|
export * from "./normalizers";
|
||||||
|
export * from "./zod-validator-error-traslator";
|
||||||
|
|||||||
@ -0,0 +1,18 @@
|
|||||||
|
import { ZodError } from "zod/v4";
|
||||||
|
import { ValidationErrorCollection, ValidationErrorDetail } from "../errors";
|
||||||
|
|
||||||
|
export function translateZodValidationError<T>(
|
||||||
|
message: string,
|
||||||
|
zodError: ZodError<T>,
|
||||||
|
errorValue?: unknown
|
||||||
|
) {
|
||||||
|
const errors: ValidationErrorDetail[] = [];
|
||||||
|
for (const issue of zodError.issues) {
|
||||||
|
errors.push({
|
||||||
|
message: issue.message,
|
||||||
|
path: issue.path.join("."),
|
||||||
|
value: errorValue ?? issue.input,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return new ValidationErrorCollection(message, errors);
|
||||||
|
}
|
||||||
@ -1,6 +1,7 @@
|
|||||||
export * from "./aggregate-root";
|
export * from "./aggregate-root";
|
||||||
export * from "./aggregate-root-repository.interface";
|
export * from "./aggregate-root-repository.interface";
|
||||||
export * from "./domain-entity";
|
export * from "./domain-entity";
|
||||||
|
export * from "./errors";
|
||||||
export * from "./events/domain-event.interface";
|
export * from "./events/domain-event.interface";
|
||||||
export * from "./helpers";
|
export * from "./helpers";
|
||||||
export * from "./specification";
|
export * from "./specification";
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
import { Result } from "@repo/rdx-utils";
|
import { Result } from "@repo/rdx-utils";
|
||||||
import * as z from "zod/v4";
|
import * as z from "zod/v4";
|
||||||
|
import { translateZodValidationError } from "../helpers";
|
||||||
import { ValueObject } from "./value-object";
|
import { ValueObject } from "./value-object";
|
||||||
|
|
||||||
interface CityProps {
|
interface CityProps {
|
||||||
@ -23,7 +24,7 @@ export class City extends ValueObject<CityProps> {
|
|||||||
const valueIsValid = City.validate(value);
|
const valueIsValid = City.validate(value);
|
||||||
|
|
||||||
if (!valueIsValid.success) {
|
if (!valueIsValid.success) {
|
||||||
return Result.fail(new Error(valueIsValid.error.issues[0].message));
|
return Result.fail(translateZodValidationError("City creation failed", valueIsValid.error));
|
||||||
}
|
}
|
||||||
return Result.ok(new City({ value }));
|
return Result.ok(new City({ value }));
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
import { Result } from "@repo/rdx-utils";
|
import { Result } from "@repo/rdx-utils";
|
||||||
import * as z from "zod/v4";
|
import * as z from "zod/v4";
|
||||||
|
import { translateZodValidationError } from "../helpers";
|
||||||
import { ValueObject } from "./value-object";
|
import { ValueObject } from "./value-object";
|
||||||
|
|
||||||
interface CountryProps {
|
interface CountryProps {
|
||||||
@ -23,7 +24,9 @@ export class Country extends ValueObject<CountryProps> {
|
|||||||
const valueIsValid = Country.validate(value);
|
const valueIsValid = Country.validate(value);
|
||||||
|
|
||||||
if (!valueIsValid.success) {
|
if (!valueIsValid.success) {
|
||||||
return Result.fail(new Error(valueIsValid.error.issues[0].message));
|
return Result.fail(
|
||||||
|
translateZodValidationError("Country creation failed", valueIsValid.error)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
return Result.ok(new Country({ value }));
|
return Result.ok(new Country({ value }));
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
import { Result } from "@repo/rdx-utils";
|
import { Result } from "@repo/rdx-utils";
|
||||||
import * as z from "zod/v4";
|
import * as z from "zod/v4";
|
||||||
|
import { translateZodValidationError } from "../helpers";
|
||||||
import { ValueObject } from "./value-object";
|
import { ValueObject } from "./value-object";
|
||||||
|
|
||||||
interface CurrencyCodeProps {
|
interface CurrencyCodeProps {
|
||||||
@ -33,7 +34,9 @@ export class CurrencyCode extends ValueObject<CurrencyCodeProps> {
|
|||||||
const valueIsValid = CurrencyCode.validate(value);
|
const valueIsValid = CurrencyCode.validate(value);
|
||||||
|
|
||||||
if (!valueIsValid.success) {
|
if (!valueIsValid.success) {
|
||||||
return Result.fail(new Error(valueIsValid.error.issues[0].message));
|
return Result.fail(
|
||||||
|
translateZodValidationError("CurrencyCode creation failed", valueIsValid.error)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
return Result.ok(new CurrencyCode({ value: valueIsValid.data }));
|
return Result.ok(new CurrencyCode({ value: valueIsValid.data }));
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
import { Result } from "@repo/rdx-utils";
|
import { Result } from "@repo/rdx-utils";
|
||||||
import * as z from "zod/v4";
|
import * as z from "zod/v4";
|
||||||
|
import { translateZodValidationError } from "../helpers";
|
||||||
import { ValueObject } from "./value-object";
|
import { ValueObject } from "./value-object";
|
||||||
|
|
||||||
interface EmailAddressProps {
|
interface EmailAddressProps {
|
||||||
@ -11,7 +12,9 @@ export class EmailAddress extends ValueObject<EmailAddressProps> {
|
|||||||
const valueIsValid = EmailAddress.validate(value);
|
const valueIsValid = EmailAddress.validate(value);
|
||||||
|
|
||||||
if (!valueIsValid.success) {
|
if (!valueIsValid.success) {
|
||||||
return Result.fail(new Error(valueIsValid.error.issues[0].message));
|
return Result.fail(
|
||||||
|
translateZodValidationError("EmailAddress creation failed", valueIsValid.error)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return Result.ok(new EmailAddress({ value: valueIsValid.data }));
|
return Result.ok(new EmailAddress({ value: valueIsValid.data }));
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
import { Result } from "@repo/rdx-utils";
|
import { Result } from "@repo/rdx-utils";
|
||||||
import * as z from "zod/v4";
|
import * as z from "zod/v4";
|
||||||
|
import { translateZodValidationError } from "../helpers";
|
||||||
import { ValueObject } from "./value-object";
|
import { ValueObject } from "./value-object";
|
||||||
|
|
||||||
interface LanguageCodeProps {
|
interface LanguageCodeProps {
|
||||||
@ -33,7 +34,9 @@ export class LanguageCode extends ValueObject<LanguageCodeProps> {
|
|||||||
const valueIsValid = LanguageCode.validate(value);
|
const valueIsValid = LanguageCode.validate(value);
|
||||||
|
|
||||||
if (!valueIsValid.success) {
|
if (!valueIsValid.success) {
|
||||||
return Result.fail(new Error(valueIsValid.error.issues[0].message));
|
return Result.fail(
|
||||||
|
translateZodValidationError("LanguageCode creation failed", valueIsValid.error)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
return Result.ok(new LanguageCode({ value: valueIsValid.data }));
|
return Result.ok(new LanguageCode({ value: valueIsValid.data }));
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
import { Result } from "@repo/rdx-utils";
|
import { Result } from "@repo/rdx-utils";
|
||||||
import * as z from "zod/v4";
|
import * as z from "zod/v4";
|
||||||
|
import { translateZodValidationError } from "../helpers";
|
||||||
import { ValueObject } from "./value-object";
|
import { ValueObject } from "./value-object";
|
||||||
|
|
||||||
interface NameProps {
|
interface NameProps {
|
||||||
@ -21,7 +22,7 @@ export class Name extends ValueObject<NameProps> {
|
|||||||
const valueIsValid = Name.validate(value);
|
const valueIsValid = Name.validate(value);
|
||||||
|
|
||||||
if (!valueIsValid.success) {
|
if (!valueIsValid.success) {
|
||||||
return Result.fail(new Error(valueIsValid.error.issues[0].message));
|
return Result.fail(translateZodValidationError("Name creation failed", valueIsValid.error));
|
||||||
}
|
}
|
||||||
return Result.ok(new Name({ value }));
|
return Result.ok(new Name({ value }));
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
import { Result } from "@repo/rdx-utils";
|
import { Result } from "@repo/rdx-utils";
|
||||||
import * as z from "zod/v4";
|
import * as z from "zod/v4";
|
||||||
|
import { translateZodValidationError } from "../helpers";
|
||||||
import { ValueObject } from "./value-object";
|
import { ValueObject } from "./value-object";
|
||||||
|
|
||||||
const DEFAULT_SCALE = 2;
|
const DEFAULT_SCALE = 2;
|
||||||
@ -42,9 +43,12 @@ export class Percentage extends ValueObject<PercentageProps> {
|
|||||||
static create(props: { value: number; scale?: number }): Result<Percentage> {
|
static create(props: { value: number; scale?: number }): Result<Percentage> {
|
||||||
const { value, scale = Percentage.DEFAULT_SCALE } = props;
|
const { value, scale = Percentage.DEFAULT_SCALE } = props;
|
||||||
|
|
||||||
const validationResult = Percentage.validate({ value, scale });
|
const valueIsValid = Percentage.validate({ value, scale });
|
||||||
if (!validationResult.success) {
|
|
||||||
return Result.fail(new Error(validationResult.error.issues.map((e) => e.message).join(", ")));
|
if (!valueIsValid.success) {
|
||||||
|
return Result.fail(
|
||||||
|
translateZodValidationError("Percentage creation failed", valueIsValid.error)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Cálculo del valor real del porcentaje
|
// Cálculo del valor real del porcentaje
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
import { Result } from "@repo/rdx-utils";
|
import { Result } from "@repo/rdx-utils";
|
||||||
import { isPossiblePhoneNumber, parsePhoneNumberWithError } from "libphonenumber-js";
|
import { isPossiblePhoneNumber, parsePhoneNumberWithError } from "libphonenumber-js";
|
||||||
import * as z from "zod/v4";
|
import * as z from "zod/v4";
|
||||||
|
import { translateZodValidationError } from "../helpers";
|
||||||
import { ValueObject } from "./value-object";
|
import { ValueObject } from "./value-object";
|
||||||
|
|
||||||
interface PhoneNumberProps {
|
interface PhoneNumberProps {
|
||||||
@ -38,14 +39,18 @@ export class PhoneNumber extends ValueObject<PhoneNumberProps> {
|
|||||||
}
|
}
|
||||||
})*/
|
})*/
|
||||||
|
|
||||||
return schema.safeParse(value);
|
return schema.safeParse(value, {
|
||||||
|
reportInput: true,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
static create(value: string): Result<PhoneNumber> {
|
static create(value: string): Result<PhoneNumber> {
|
||||||
const valueIsValid = PhoneNumber.validate(value);
|
const valueIsValid = PhoneNumber.validate(value);
|
||||||
|
|
||||||
if (!valueIsValid.success) {
|
if (!valueIsValid.success) {
|
||||||
return Result.fail(new Error(valueIsValid.error.issues[0].message));
|
return Result.fail(
|
||||||
|
translateZodValidationError("PhoneNumber creation failed", valueIsValid.error)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return Result.ok(new PhoneNumber({ value: valueIsValid.data }));
|
return Result.ok(new PhoneNumber({ value: valueIsValid.data }));
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
import { Result } from "@repo/rdx-utils";
|
import { Result } from "@repo/rdx-utils";
|
||||||
import * as z from "zod/v4";
|
import * as z from "zod/v4";
|
||||||
|
import { translateZodValidationError } from "../helpers";
|
||||||
import { ValueObject } from "./value-object";
|
import { ValueObject } from "./value-object";
|
||||||
|
|
||||||
interface PostalCodeProps {
|
interface PostalCodeProps {
|
||||||
@ -31,7 +32,9 @@ export class PostalCode extends ValueObject<PostalCodeProps> {
|
|||||||
const valueIsValid = PostalCode.validate(value);
|
const valueIsValid = PostalCode.validate(value);
|
||||||
|
|
||||||
if (!valueIsValid.success) {
|
if (!valueIsValid.success) {
|
||||||
return Result.fail(new Error(valueIsValid.error.issues[0].message));
|
return Result.fail(
|
||||||
|
translateZodValidationError("PostalCode creation failed", valueIsValid.error)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
return Result.ok(new PostalCode({ value: valueIsValid.data }));
|
return Result.ok(new PostalCode({ value: valueIsValid.data }));
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
import { Result } from "@repo/rdx-utils";
|
import { Result } from "@repo/rdx-utils";
|
||||||
import * as z from "zod/v4";
|
import * as z from "zod/v4";
|
||||||
|
import { translateZodValidationError } from "../helpers";
|
||||||
import { ValueObject } from "./value-object";
|
import { ValueObject } from "./value-object";
|
||||||
|
|
||||||
interface ProvinceProps {
|
interface ProvinceProps {
|
||||||
@ -23,7 +24,9 @@ export class Province extends ValueObject<ProvinceProps> {
|
|||||||
const valueIsValid = Province.validate(value);
|
const valueIsValid = Province.validate(value);
|
||||||
|
|
||||||
if (!valueIsValid.success) {
|
if (!valueIsValid.success) {
|
||||||
return Result.fail(new Error(valueIsValid.error.issues[0].message));
|
return Result.fail(
|
||||||
|
translateZodValidationError("Province creation failed", valueIsValid.error)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
return Result.ok(new Province({ value }));
|
return Result.ok(new Province({ value }));
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
import { Result } from "@repo/rdx-utils";
|
import { Result } from "@repo/rdx-utils";
|
||||||
import * as z from "zod/v4";
|
import * as z from "zod/v4";
|
||||||
|
import { translateZodValidationError } from "../helpers";
|
||||||
import { ValueObject } from "./value-object";
|
import { ValueObject } from "./value-object";
|
||||||
|
|
||||||
const DEFAULT_SCALE = 2;
|
const DEFAULT_SCALE = 2;
|
||||||
@ -33,7 +34,7 @@ export class Quantity extends ValueObject<QuantityProps> {
|
|||||||
const checkProps = Quantity.validate(props);
|
const checkProps = Quantity.validate(props);
|
||||||
|
|
||||||
if (!checkProps.success) {
|
if (!checkProps.success) {
|
||||||
return Result.fail(new Error(checkProps.error.issues[0].message));
|
return Result.fail(translateZodValidationError("Quantity creation failed", checkProps.error));
|
||||||
}
|
}
|
||||||
return Result.ok(new Quantity({ ...(checkProps.data as QuantityProps) }));
|
return Result.ok(new Quantity({ ...(checkProps.data as QuantityProps) }));
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
import { Result } from "@repo/rdx-utils";
|
import { Result } from "@repo/rdx-utils";
|
||||||
import * as z from "zod/v4";
|
import * as z from "zod/v4";
|
||||||
|
import { translateZodValidationError } from "../helpers";
|
||||||
import { ValueObject } from "./value-object";
|
import { ValueObject } from "./value-object";
|
||||||
|
|
||||||
interface SlugProps {
|
interface SlugProps {
|
||||||
@ -26,7 +27,7 @@ export class Slug extends ValueObject<SlugProps> {
|
|||||||
const valueIsValid = Slug.validate(value);
|
const valueIsValid = Slug.validate(value);
|
||||||
|
|
||||||
if (!valueIsValid.success) {
|
if (!valueIsValid.success) {
|
||||||
return Result.fail(new Error(valueIsValid.error.issues[0].message));
|
return Result.fail(translateZodValidationError("Slug creation failed", valueIsValid.error));
|
||||||
}
|
}
|
||||||
// biome-ignore lint/style/noNonNullAssertion: <explanation>
|
// biome-ignore lint/style/noNonNullAssertion: <explanation>
|
||||||
return Result.ok(new Slug({ value: valueIsValid.data! }));
|
return Result.ok(new Slug({ value: valueIsValid.data! }));
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
import { Result } from "@repo/rdx-utils";
|
import { Result } from "@repo/rdx-utils";
|
||||||
import * as z from "zod/v4";
|
import * as z from "zod/v4";
|
||||||
|
import { translateZodValidationError } from "../helpers";
|
||||||
import { ValueObject } from "./value-object";
|
import { ValueObject } from "./value-object";
|
||||||
|
|
||||||
interface StreetProps {
|
interface StreetProps {
|
||||||
@ -23,7 +24,7 @@ export class Street extends ValueObject<StreetProps> {
|
|||||||
const valueIsValid = Street.validate(value);
|
const valueIsValid = Street.validate(value);
|
||||||
|
|
||||||
if (!valueIsValid.success) {
|
if (!valueIsValid.success) {
|
||||||
return Result.fail(new Error(valueIsValid.error.issues[0].message));
|
return Result.fail(translateZodValidationError("Street creation failed", valueIsValid.error));
|
||||||
}
|
}
|
||||||
return Result.ok(new Street({ value }));
|
return Result.ok(new Street({ value }));
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
import { Result } from "@repo/rdx-utils";
|
import { Result } from "@repo/rdx-utils";
|
||||||
import * as z from "zod/v4";
|
import * as z from "zod/v4";
|
||||||
|
import { translateZodValidationError } from "../helpers";
|
||||||
import { ValueObject } from "./value-object";
|
import { ValueObject } from "./value-object";
|
||||||
|
|
||||||
interface TaxCodeProps {
|
interface TaxCodeProps {
|
||||||
@ -30,7 +31,9 @@ export class TaxCode extends ValueObject<TaxCodeProps> {
|
|||||||
const valueIsValid = TaxCode.validate(value);
|
const valueIsValid = TaxCode.validate(value);
|
||||||
|
|
||||||
if (!valueIsValid.success) {
|
if (!valueIsValid.success) {
|
||||||
return Result.fail(new Error(valueIsValid.error.issues[0].message));
|
return Result.fail(
|
||||||
|
translateZodValidationError("TaxCode creation failed", valueIsValid.error)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
// biome-ignore lint/style/noNonNullAssertion: <explanation>
|
// biome-ignore lint/style/noNonNullAssertion: <explanation>
|
||||||
return Result.ok(new TaxCode({ value: valueIsValid.data! }));
|
return Result.ok(new TaxCode({ value: valueIsValid.data! }));
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
import { Result } from "@repo/rdx-utils";
|
import { Result } from "@repo/rdx-utils";
|
||||||
import * as z from "zod/v4";
|
import * as z from "zod/v4";
|
||||||
|
import { translateZodValidationError } from "../helpers";
|
||||||
import { ValueObject } from "./value-object";
|
import { ValueObject } from "./value-object";
|
||||||
|
|
||||||
interface TextValueProps {
|
interface TextValueProps {
|
||||||
@ -24,7 +25,9 @@ export class TextValue extends ValueObject<TextValueProps> {
|
|||||||
const valueIsValid = TextValue.validate(value);
|
const valueIsValid = TextValue.validate(value);
|
||||||
|
|
||||||
if (!valueIsValid.success) {
|
if (!valueIsValid.success) {
|
||||||
return Result.fail(new Error(valueIsValid.error.issues[0].message));
|
return Result.fail(
|
||||||
|
translateZodValidationError("TextValue creation failed", valueIsValid.error)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
return Result.ok(new TextValue({ value }));
|
return Result.ok(new TextValue({ value }));
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
import { Result } from "@repo/rdx-utils";
|
import { Result } from "@repo/rdx-utils";
|
||||||
import * as z from "zod/v4";
|
import * as z from "zod/v4";
|
||||||
|
import { translateZodValidationError } from "../helpers";
|
||||||
import { ValueObject } from "./value-object";
|
import { ValueObject } from "./value-object";
|
||||||
|
|
||||||
interface TINNumberProps {
|
interface TINNumberProps {
|
||||||
@ -28,7 +29,9 @@ export class TINNumber extends ValueObject<TINNumberProps> {
|
|||||||
const valueIsValid = TINNumber.validate(value);
|
const valueIsValid = TINNumber.validate(value);
|
||||||
|
|
||||||
if (!valueIsValid.success) {
|
if (!valueIsValid.success) {
|
||||||
return Result.fail(new Error(valueIsValid.error.issues[0].message));
|
return Result.fail(
|
||||||
|
translateZodValidationError("TINNumber creation failed", valueIsValid.error)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
return Result.ok(new TINNumber({ value: valueIsValid.data }));
|
return Result.ok(new TINNumber({ value: valueIsValid.data }));
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
import { Result } from "@repo/rdx-utils";
|
import { Result } from "@repo/rdx-utils";
|
||||||
import * as z from "zod/v4";
|
import * as z from "zod/v4";
|
||||||
|
import { translateZodValidationError } from "../helpers";
|
||||||
import { ValueObject } from "./value-object";
|
import { ValueObject } from "./value-object";
|
||||||
|
|
||||||
interface URLAddressProps {
|
interface URLAddressProps {
|
||||||
@ -11,14 +12,28 @@ export class URLAddress extends ValueObject<URLAddressProps> {
|
|||||||
const valueIsValid = URLAddress.validate(value);
|
const valueIsValid = URLAddress.validate(value);
|
||||||
|
|
||||||
if (!valueIsValid.success) {
|
if (!valueIsValid.success) {
|
||||||
return Result.fail(new Error(valueIsValid.error.issues[0].message));
|
return Result.fail(
|
||||||
|
translateZodValidationError("URLAddress creation failed", valueIsValid.error)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return Result.ok(new URLAddress({ value: valueIsValid.data }));
|
return Result.ok(new URLAddress({ value: valueIsValid.data }));
|
||||||
}
|
}
|
||||||
|
|
||||||
private static validate(value: string) {
|
private static validate(value: string) {
|
||||||
const schema = z.url({ message: "Invalid URL format" });
|
const schema = z.string().refine((value) => {
|
||||||
|
const urlPattern = new RegExp(
|
||||||
|
"^(https?:\\/\\/)?" + // protocolo opcional
|
||||||
|
"((([a-z\\d]([a-z\\d-]*[a-z\\d])*)\\.)+[a-z]{2,}|" + // nombre de dominio
|
||||||
|
"((\\d{1,3}\\.){3}\\d{1,3}))" + // o dirección IP (v4)
|
||||||
|
"(\\:\\d+)?(\\/[-a-z\\d%_.~+]*)*" + // puerto y ruta
|
||||||
|
"(\\?[;&a-z\\d%_.~+=-]*)?" + // query string
|
||||||
|
"(\\#[-a-z\\d_]*)?$",
|
||||||
|
"i" // fragment locator
|
||||||
|
);
|
||||||
|
return urlPattern.test(value);
|
||||||
|
}, "Invalid URL format");
|
||||||
|
|
||||||
return schema.safeParse(value);
|
return schema.safeParse(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
import { Result } from "@repo/rdx-utils";
|
import { Result } from "@repo/rdx-utils";
|
||||||
import * as z from "zod/v4";
|
import * as z from "zod/v4";
|
||||||
|
import { translateZodValidationError } from "../helpers";
|
||||||
import { ValueObject } from "./value-object";
|
import { ValueObject } from "./value-object";
|
||||||
|
|
||||||
interface UtcDateProps {
|
interface UtcDateProps {
|
||||||
@ -33,8 +34,9 @@ export class UtcDate extends ValueObject<UtcDateProps> {
|
|||||||
*/
|
*/
|
||||||
static createFromISO(isoDateString: string): Result<UtcDate, Error> {
|
static createFromISO(isoDateString: string): Result<UtcDate, Error> {
|
||||||
const dateIsValid = UtcDate.validate(isoDateString);
|
const dateIsValid = UtcDate.validate(isoDateString);
|
||||||
|
|
||||||
if (!dateIsValid.success) {
|
if (!dateIsValid.success) {
|
||||||
return Result.fail(new Error(`Invalid UTC date format: ${isoDateString}`));
|
return Result.fail(translateZodValidationError("UtcDate creation failed", dateIsValid.error));
|
||||||
}
|
}
|
||||||
|
|
||||||
return Result.ok(new UtcDate({ value: isoDateString }));
|
return Result.ok(new UtcDate({ value: isoDateString }));
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user