metis-desk/modules/companies/src/api/application/person-photo.use-cases.ts
2026-10-10 12:01:58 +02:00

57 lines
2.2 KiB
TypeScript

import { Result } from "@repo/rdx-utils";
import { z } from "zod/v4";
import { PERSON_PHOTO_LIMITS } from "../../common/person-photo";
import { PersonPhotoError } from "../domain/person-photo-error";
export type PersonPhoto = Readonly<{ data: Uint8Array; version: string }>;
export interface IPersonPhotoRepository {
exists(companyId: string, personId: string): Promise<boolean>;
get(personId: string): Promise<PersonPhoto | null>;
replace(companyId: string, personId: string, photo: PersonPhoto | null): Promise<boolean>;
}
export interface IPersonPhotoProcessor {
optimize(data: Uint8Array): Promise<Result<PersonPhoto, PersonPhotoError>>;
}
export class PersonPhotoUseCases {
constructor(
private readonly repository: IPersonPhotoRepository,
private readonly processor: IPersonPhotoProcessor
) {}
async get(personId: string) {
if (!z.uuid().safeParse(personId).success)
return Result.fail(new PersonPhotoError("INVALID_REQUEST"));
const photo = await this.repository.get(personId);
return photo ? Result.ok(photo) : Result.fail(new PersonPhotoError("PHOTO_NOT_FOUND"));
}
async save(companyId: string, personId: string, data: Uint8Array) {
if (!z.uuid().safeParse(companyId).success || !z.uuid().safeParse(personId).success)
return Result.fail(new PersonPhotoError("INVALID_REQUEST"));
if (data.length > PERSON_PHOTO_LIMITS.inputBytes)
return Result.fail(new PersonPhotoError("PHOTO_TOO_LARGE"));
if (!(await this.repository.exists(companyId, personId)))
return Result.fail(new PersonPhotoError("PERSON_NOT_FOUND"));
const processed = await this.processor.optimize(data);
if (!processed.isSuccess) return Result.fail(processed.error);
return (await this.repository.replace(companyId, personId, processed.data))
? Result.ok(processed.data.version)
: Result.fail(new PersonPhotoError("PERSON_NOT_FOUND"));
}
async remove(companyId: string, personId: string) {
if (!z.uuid().safeParse(companyId).success || !z.uuid().safeParse(personId).success)
return Result.fail(new PersonPhotoError("INVALID_REQUEST"));
return (await this.repository.replace(companyId, personId, null))
? Result.ok(null)
: Result.fail(new PersonPhotoError("PERSON_NOT_FOUND"));
}
}