import { z } from "zod"; import { Maybe, Result } from "../../helpers"; import { ValueObject } from "./value-object"; // 📌 Validaciones usando `zod` const postalCodeSchema = z .string() .min(4, "Invalid postal code format") .max(10, "Invalid postal code format") .regex(/^\d{4,10}$/, { message: "Invalid postal code format", }); const streetSchema = z.string().min(2).max(255); const street2Schema = z.string().optional(); const citySchema = z.string().min(2).max(50); const stateSchema = z.string().min(2).max(50); const countrySchema = z.string().min(2).max(56); interface IPostalAddressProps { street: string; street2?: string; city: string; postalCode: string; state: string; country: string; } export class PostalAddress extends ValueObject { protected static validate(values: IPostalAddressProps) { return z .object({ street: streetSchema, street2: street2Schema, city: citySchema, postalCode: postalCodeSchema, state: stateSchema, country: countrySchema, }) .safeParse(values); } static create(values: IPostalAddressProps): Result { const valueIsValid = PostalAddress.validate(values); if (!valueIsValid.success) { return Result.fail(new Error(valueIsValid.error.errors[0].message)); } return Result.ok(new PostalAddress(values)); } static createNullable(values?: IPostalAddressProps): Result, Error> { if (!values || Object.values(values).every((value) => value.trim() === "")) { return Result.ok(Maybe.none()); } return PostalAddress.create(values!).map((value) => Maybe.some(value)); } static update( oldAddress: PostalAddress, data: Partial ): Result { return PostalAddress.create({ street: data.street ?? oldAddress.street, street2: data.street2?.getOrUndefined() ?? oldAddress.street2.getOrUndefined(), city: data.city ?? oldAddress.city, postalCode: data.postalCode ?? oldAddress.postalCode, state: data.state ?? oldAddress.state, country: data.country ?? oldAddress.country, }).getOrElse(this); } get street(): string { return this.props.street; } get street2(): Maybe { return Maybe.fromNullable(this.props.street2); } get city(): string { return this.props.city; } get postalCode(): string { return this.props.postalCode; } get state(): string { return this.props.state; } get country(): string { return this.props.country; } getValue(): IPostalAddressProps { return this.props; } toString(): string { return `${this.props.street}, ${this.props.street2}, ${this.props.city}, ${this.props.postalCode}, ${this.props.state}, ${this.props.country}`; } }