metis-desk/modules/assets/src/api/domain/asset-infrastructure.aggregate.ts

88 lines
2.2 KiB
TypeScript
Raw Normal View History

2026-10-17 15:01:16 +00:00
import type { UniqueID } from "@repo/rdx-ddd";
import { AggregateRoot } from "@repo/rdx-ddd";
import { Result } from "@repo/rdx-utils";
import { z } from "zod/v4";
import { AssetCatalogError } from "./asset-definition";
import { InfrastructureRevision } from "./infrastructure-revision.entity";
import type { InfrastructureValues } from "./value-objects/infrastructure-values.vo";
type InfrastructureProps = Readonly<{
companyId: UniqueID;
assetId: UniqueID;
history: readonly InfrastructureRevision[];
}>;
export class AssetInfrastructure extends AggregateRoot<InfrastructureProps> {
private constructor(props: InfrastructureProps, id?: UniqueID) {
super(Object.freeze({ ...props, history: Object.freeze([...props.history]) }), id);
}
static create(
companyId: UniqueID,
assetId: UniqueID,
values: InfrastructureValues,
actorId: UniqueID,
recordedAt: string
) {
if (!z.iso.datetime().safeParse(recordedAt).success) {
return Result.fail(new AssetCatalogError("INVALID_REQUEST"));
}
return Result.ok(
new AssetInfrastructure({
companyId,
assetId,
history: [InfrastructureRevision.create({ values, actorId, recordedAt })],
})
);
}
static rehydrate(id: UniqueID, props: InfrastructureProps) {
return new AssetInfrastructure(props, id);
}
get companyId() {
return this.props.companyId;
}
get assetId() {
return this.props.assetId;
}
get history() {
return this.props.history;
}
get values() {
const latest = this.history.at(-1);
if (!latest) {
throw new Error("Infraestructura sin revisión.");
}
return latest.values;
}
update(values: InfrastructureValues, actorId: UniqueID, recordedAt: string) {
if (!z.iso.datetime().safeParse(recordedAt).success) {
return Result.fail(new AssetCatalogError("INVALID_REQUEST"));
}
return Result.ok(
this.values.equals(values)
? this
: new AssetInfrastructure(
{
...this.props,
history: [
...this.history,
InfrastructureRevision.create({ values, actorId, recordedAt }),
],
},
this.id
)
);
}
}