metis-desk/modules/assets/src/api/domain/brand.aggregate.ts
2026-10-08 16:43:34 +02:00

72 lines
1.7 KiB
TypeScript

import type { Name, UniqueID } from "@repo/rdx-ddd";
import { AggregateRoot } from "@repo/rdx-ddd";
import { Result } from "@repo/rdx-utils";
import { z } from "zod/v4";
export const BrandInputSchema = z.strictObject({
name: z.string().trim().min(1).max(100),
active: z.boolean(),
});
export type BrandInput = z.infer<typeof BrandInputSchema>;
export class BrandError extends Error {
constructor(public readonly code: string) {
super(code);
}
}
export type BrandProps = Readonly<{ name: Name; active: boolean; builtin: boolean }>;
export class Brand extends AggregateRoot<BrandProps> {
private constructor(props: BrandProps, id?: UniqueID) {
super(Object.freeze({ ...props }), id);
}
static create(props: BrandProps): Result<Brand, BrandError> {
return Result.ok(new Brand(props));
}
static rehydrate(props: BrandProps, id: UniqueID) {
return new Brand(props, id);
}
get name() {
return this.props.name;
}
get active() {
return this.props.active;
}
get builtin() {
return this.props.builtin;
}
update(props: BrandProps): Result<Brand, BrandError> {
if (props.builtin !== this.builtin || (this.builtin && !this.name.equals(props.name))) {
return Result.fail(new BrandError("BUILTIN_PROTECTED"));
}
if (this.name.equals(props.name) && this.active === props.active) {
return Result.ok(this);
}
return Result.ok(new Brand(props, this.id));
}
}
export const BUILTIN_BRANDS = [
"Acer",
"Apple",
"ASUS",
"Brother",
"Canon",
"Clónico",
"Dell",
"Epson",
"HP",
"Huawei",
"Intel",
"Kyocera",
"Lenovo",
"LG",
"Logitech",
"Microsoft",
"MikroTik",
"MSI",
"QNAP",
"Samsung",
"Synology",
"TP-Link",
"Ubiquiti",
"Zebra",
] as const;