93 lines
2.8 KiB
TypeScript
93 lines
2.8 KiB
TypeScript
|
|
import { Name, UniqueID } from "@repo/rdx-ddd";
|
||
|
|
import { Result } from "@repo/rdx-utils";
|
||
|
|
import { z } from "zod/v4";
|
||
|
|
|
||
|
|
import { AssetCatalogError } from "../asset-definition";
|
||
|
|
|
||
|
|
export const RelationshipValuesSchema = z.strictObject({
|
||
|
|
sourceId: z.uuid(),
|
||
|
|
targetId: z.uuid(),
|
||
|
|
typeId: z.uuid(),
|
||
|
|
name: z.string().min(1).max(100),
|
||
|
|
inverseName: z.string().min(1).max(100),
|
||
|
|
symmetric: z.boolean(),
|
||
|
|
notes: z.string().max(10000),
|
||
|
|
});
|
||
|
|
export type RelationshipValuesData = z.infer<typeof RelationshipValuesSchema>;
|
||
|
|
|
||
|
|
export class AssetRelationshipValues {
|
||
|
|
private constructor(
|
||
|
|
public readonly sourceId: UniqueID,
|
||
|
|
public readonly targetId: UniqueID,
|
||
|
|
public readonly typeId: UniqueID,
|
||
|
|
public readonly name: Name,
|
||
|
|
public readonly inverseName: Name,
|
||
|
|
public readonly symmetric: boolean,
|
||
|
|
public readonly notes: string
|
||
|
|
) {
|
||
|
|
Object.freeze(this);
|
||
|
|
}
|
||
|
|
static create(input: RelationshipValuesData): Result<AssetRelationshipValues, AssetCatalogError> {
|
||
|
|
const parsed = RelationshipValuesSchema.safeParse(input);
|
||
|
|
const source = UniqueID.create(input.sourceId);
|
||
|
|
const target = UniqueID.create(input.targetId);
|
||
|
|
const type = UniqueID.create(input.typeId);
|
||
|
|
const name = Name.create(input.name, 100);
|
||
|
|
const inverse = Name.create(input.symmetric ? input.name : input.inverseName, 100);
|
||
|
|
if (
|
||
|
|
!(
|
||
|
|
parsed.success &&
|
||
|
|
source.isSuccess &&
|
||
|
|
target.isSuccess &&
|
||
|
|
type.isSuccess &&
|
||
|
|
name.isSuccess &&
|
||
|
|
inverse.isSuccess
|
||
|
|
)
|
||
|
|
) {
|
||
|
|
return Result.fail(new AssetCatalogError("INVALID_REQUEST"));
|
||
|
|
}
|
||
|
|
if (source.data.equals(target.data)) {
|
||
|
|
return Result.fail(new AssetCatalogError("SELF_RELATIONSHIP"));
|
||
|
|
}
|
||
|
|
return Result.ok(
|
||
|
|
new AssetRelationshipValues(
|
||
|
|
source.data,
|
||
|
|
target.data,
|
||
|
|
type.data,
|
||
|
|
name.data,
|
||
|
|
inverse.data,
|
||
|
|
input.symmetric,
|
||
|
|
input.notes.trim()
|
||
|
|
)
|
||
|
|
);
|
||
|
|
}
|
||
|
|
toPrimitive(): RelationshipValuesData {
|
||
|
|
return {
|
||
|
|
sourceId: this.sourceId.toPrimitive(),
|
||
|
|
targetId: this.targetId.toPrimitive(),
|
||
|
|
typeId: this.typeId.toPrimitive(),
|
||
|
|
name: this.name.toPrimitive(),
|
||
|
|
inverseName: this.inverseName.toPrimitive(),
|
||
|
|
symmetric: this.symmetric,
|
||
|
|
notes: this.notes,
|
||
|
|
};
|
||
|
|
}
|
||
|
|
equals(other: AssetRelationshipValues): boolean {
|
||
|
|
return (
|
||
|
|
this.key() === other.key() &&
|
||
|
|
this.name.equals(other.name) &&
|
||
|
|
this.inverseName.equals(other.inverseName) &&
|
||
|
|
this.symmetric === other.symmetric &&
|
||
|
|
this.notes === other.notes
|
||
|
|
);
|
||
|
|
}
|
||
|
|
/** Identifica un vínculo; las relaciones simétricas normalizan el orden de sus extremos. */
|
||
|
|
key(): string {
|
||
|
|
const ids = [this.sourceId.toPrimitive(), this.targetId.toPrimitive()];
|
||
|
|
if (this.symmetric) {
|
||
|
|
ids.sort();
|
||
|
|
}
|
||
|
|
return [this.typeId.toPrimitive(), ...ids].join(":");
|
||
|
|
}
|
||
|
|
}
|