import { v4 as uuidv4 } from "uuid"; import { z } from "zod"; import { Result } from "../result"; import { ValueObject } from "./value-object"; export const UNDEFINED_ID = undefined; export class UniqueID extends ValueObject { protected readonly _hasId!: boolean; protected constructor(id?: string) { super(id); this._hasId = id != UNDEFINED_ID; } static create(id?: string, generateOnEmpty: boolean = false): Result { if (id === null) { return Result.fail(new Error("ID cannot be null")); } const trimmedId = id?.trim(); if (!trimmedId) { return generateOnEmpty ? UniqueID.generateNewID() : Result.ok(new UniqueID(UNDEFINED_ID)); } const result = UniqueID.validate(trimmedId); return result.success ? Result.ok(new UniqueID(result.data)) : Result.fail(new Error(result.error.errors[0].message)); } static generate(): UniqueID { return new UniqueID(uuidv4()); } static validate(id: string) { const schema = z.string().uuid({ message: "Invalid UUID format" }); return schema.safeParse(id.trim()); } static generateNewID(): Result { return Result.ok(new UniqueID(uuidv4())); } static generateUndefinedID(): Result { return Result.ok(new UniqueID(UNDEFINED_ID)); } isDefined(): boolean { return this._hasId; } }