metis-desk/modules/resources/src/api/domain/resource.aggregate.ts

90 lines
2.8 KiB
TypeScript
Raw Normal View History

2026-10-08 14:43:34 +00:00
import type { UniqueID } from "@repo/rdx-ddd";
import { AggregateRoot } from "@repo/rdx-ddd";
2026-10-05 11:13:51 +00:00
import { Result } from "@repo/rdx-utils";
import { ResourceCatalogError } from "./resource-definition";
import { ResourceRevision } from "./resource-revision.entity";
2026-10-09 08:38:19 +00:00
import type { ResourceSpecification, ResourceValues } from "./value-objects/resource-values.vo";
2026-10-05 11:13:51 +00:00
type ResourceProps = Readonly<{
companyId: UniqueID;
specification: ResourceSpecification;
values: ResourceValues;
history: readonly ResourceRevision[];
}>;
export class Resource extends AggregateRoot<ResourceProps> {
private constructor(props: ResourceProps, id?: UniqueID) {
super({ ...props, history: Object.freeze([...props.history]) }, id);
}
static create(
companyId: UniqueID,
specification: ResourceSpecification,
values: ResourceValues,
actorId: UniqueID,
recordedAt: string
) {
return Result.ok<Resource>(
new Resource({
companyId,
specification,
values,
history: [ResourceRevision.create({ values, actorId, recordedAt })],
})
);
}
static rehydrate(props: ResourceProps, id: UniqueID) {
return new Resource(props, id);
}
get companyId() {
return this.props.companyId;
}
get specification() {
return this.props.specification;
}
get values() {
return this.props.values;
}
get history() {
return this.props.history;
}
update(
values: ResourceValues,
actorId: UniqueID,
recordedAt: string
): Result<Resource, ResourceCatalogError> {
if (values.toPrimitive().templateId !== this.values.toPrimitive().templateId) {
return Result.fail(new ResourceCatalogError("TEMPLATE_FIXED"));
}
2026-10-05 15:01:32 +00:00
const previous = this.values.toPrimitive().integration;
const next = values.toPrimitive().integration;
if (
previous?.kind !== next?.kind ||
(previous?.kind === "mailbox" &&
next?.kind === "mailbox" &&
(previous.mailboxKind !== next.mailboxKind ||
previous.addressFieldId !== next.addressFieldId ||
previous.contextFieldId !== next.contextFieldId)) ||
(previous?.kind === "access" &&
next?.kind === "access" &&
(previous.referenceFieldId !== next.referenceFieldId ||
previous.resourceTypeId !== next.resourceTypeId ||
previous.systemId !== next.systemId ||
previous.environmentId !== next.environmentId))
) {
return Result.fail(new ResourceCatalogError("CONTEXT_FIXED"));
}
2026-10-05 11:13:51 +00:00
return Result.ok(
this.values.equals(values)
? this
: new Resource(
{
...this.props,
values,
history: [...this.history, ResourceRevision.create({ values, actorId, recordedAt })],
},
this.id
)
);
}
}