UNPKG

@synet/patterns

Version:

Robust, battle-tested collection of stable patterns used in Synet packages

92 lines (91 loc) 2.76 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.ValueObject = void 0; /** * Base class for Value Objects - immutable objects defined by their property values. * * Value Objects encapsulate domain concepts that have no distinct identity. * Two Value Objects are equal when all their properties are equal. * * @see /docs/value-object.md for detailed documentation and examples * * @template T - The shape of properties that define this Value Object * @example * class Email extends ValueObject<{ address: string }> { * private constructor(props: { address: string }) { * super(props); * } * * public static create(address: string): Result<Email> { * if (!address.includes('@')) { * return Result.fail('Email must contain @ symbol'); * } * return Result.success(new Email({ address })); * } * * get value(): string { * return this.props.address; * } * } */ class ValueObject { /** * Creates a new Value Object with the given properties. * The properties are frozen to ensure immutability. */ constructor(props) { this.props = Object.freeze({ ...props }); } /** * Checks if this Value Object is equal to another Value Object. * Two Value Objects are considered equal if all their properties are equal. */ equals(vo) { if (vo === null || vo === undefined) { return false; } if (!(vo instanceof this.constructor)) { return false; } return this.isEqual(this.props, vo.props); } /** * Deep comparison of properties. * This handles nested objects and arrays properly. */ isEqual(obj1, obj2) { if (obj1 === obj2) { return true; } if (typeof obj1 !== "object" || obj1 === null || typeof obj2 !== "object" || obj2 === null) { return obj1 === obj2; } const keys1 = Object.keys(obj1); const keys2 = Object.keys(obj2); if (keys1.length !== keys2.length) { return false; } return keys1.every((key) => { // Type assertion needed because TypeScript doesn't recognize keys1/keys2 are keys of obj1/obj2 return (keys2.includes(key) && this.isEqual(obj1[key], obj2[key])); }); } /** * Returns a string representation of this Value Object. */ toString() { return JSON.stringify(this.props); } /** * Returns a shallow copy of the props. * This can be used when you need to access the raw data. */ toObject() { return { ...this.props }; } } exports.ValueObject = ValueObject;