import { errAsync, ResultAsync } from "neverthrow"; import { db } from "@pkg/db"; import { type Err } from "@pkg/result"; import { FlowExecCtx } from "@core/flow.execution.context"; import { CreateDevice, Device, DeviceStatus, UpdateDevice } from "./data"; import { DeviceRepository } from "./repository"; import { deviceErrors } from "./errors"; export class DeviceController { constructor(private repo: DeviceRepository) {} list(fctx: FlowExecCtx): ResultAsync { return this.repo.list(fctx); } getById(fctx: FlowExecCtx, id: number): ResultAsync { return this.repo.getById(fctx, id); } create(fctx: FlowExecCtx, data: CreateDevice): ResultAsync { return this.repo.create(fctx, data); } update( fctx: FlowExecCtx, id: number, data: UpdateDevice, ): ResultAsync { return this.repo.update(fctx, id, data); } delete(fctx: FlowExecCtx, id: number): ResultAsync { return this.repo.delete(fctx, id); } setStatus( fctx: FlowExecCtx, id: number, status: DeviceStatus, ): ResultAsync { return this.repo.setStatus(fctx, id, status); } /** * Mark a device as busy for an incoming session. * Only succeeds if the device is currently online. */ allocate(fctx: FlowExecCtx, id: number): ResultAsync { return this.repo.getById(fctx, id).andThen((dev) => { if (dev.status !== DeviceStatus.ONLINE) { return errAsync(deviceErrors.deviceNotAvailable(fctx, id)); } return this.repo.setStatus(fctx, id, DeviceStatus.BUSY); }); } /** * Release a device back to online after a session ends. */ release(fctx: FlowExecCtx, id: number): ResultAsync { return this.repo.setStatus(fctx, id, DeviceStatus.ONLINE); } } export function getDeviceController(): DeviceController { return new DeviceController(new DeviceRepository(db)); }