import { UniqueID } from "@repo/rdx-ddd"; import { z } from "zod/v4"; import { WorkProfileValues } from "../../domain/value-objects/work-profile-values"; import { WorkProfile } from "../../domain/work-profile.aggregate"; import { WorkProfileRevision } from "../../domain/work-profile-revision.entity"; import { WorkProfileInputSchema } from "../../domain/work-profile-values"; export function profileIdentity(value: string) { const id = UniqueID.create(value); if (!id.isSuccess) { throw new Error("Identidad de perfil persistida inconsistente."); } return id.data; } export function persistedJson(value: unknown): unknown { return typeof value === "string" ? JSON.parse(value) : value; } export type ProfileRow = { id: string; companyId: string; personId: string; accountId: string | null; assetId: string; values: unknown; currentKey: string | null; }; export type ProfileRevisionRow = { id: string; profileId: string; accountId: string | null; position: number; actorId: string; recordedAt: string; values: unknown; }; function valuesOf(raw: unknown) { const values = WorkProfileValues.create(WorkProfileInputSchema.parse(persistedJson(raw))); if (!values.isSuccess) { throw new Error("Valores de perfil persistidos inconsistentes."); } return values.data; } export class WorkProfilePersistenceMapper { toDomain(row: ProfileRow, revisions: readonly ProfileRevisionRow[]) { const values = valuesOf(row.values); const ordered = [...revisions].sort((a, b) => a.position - b.position); const history = ordered.map((revision, position) => { const revisionValues = valuesOf(revision.values); if ( revision.position !== position || !z.iso.datetime().safeParse(revision.recordedAt).success || revision.recordedAt < (ordered[position - 1]?.recordedAt ?? "") || !values.sameTarget(revisionValues) || revision.accountId !== revisionValues.toPrimitive().accountId ) { throw new Error("Historial de perfil persistido inconsistente."); } return WorkProfileRevision.rehydrate( { values: revisionValues, actorId: profileIdentity(revision.actorId), recordedAt: revision.recordedAt, }, profileIdentity(revision.id) ); }); if ( !history.at(-1)?.values.equals(values) || row.personId !== values.personId.toPrimitive() || row.accountId !== values.toPrimitive().accountId || row.assetId !== values.assetId.toPrimitive() || row.currentKey !== (values.active ? [row.personId, row.assetId].join(":") : null) ) { throw new Error("Referencias de perfil persistidas inconsistentes."); } return WorkProfile.rehydrate( { companyId: profileIdentity(row.companyId), values, history }, profileIdentity(row.id) ); } toPersistence(item: WorkProfile) { const values = item.values.toPrimitive(); return { root: { id: item.id.toPrimitive(), companyId: item.companyId.toPrimitive(), personId: values.personId, accountId: values.accountId, assetId: values.assetId, values: JSON.stringify(values), currentKey: item.values.active ? [values.personId, values.assetId].join(":") : null, }, revisions: item.history.map((revision, position) => ({ id: revision.id.toPrimitive(), profileId: item.id.toPrimitive(), accountId: revision.values.toPrimitive().accountId, position, actorId: revision.actorId.toPrimitive(), recordedAt: revision.recordedAt, values: JSON.stringify(revision.values.toPrimitive()), })), }; } }