import { ControlPlaneBadRequestError, ControlPlaneNotFoundError, ControlPlaneStorageError, } from "#api"; import { ControlPlanePersistenceError } from "#persistence"; import * as Effect from "effect/Effect"; const unknownPersistenceError = ( operation: string, cause: unknown, details: string, ): ControlPlanePersistenceError => new ControlPlanePersistenceError({ operation, message: cause instanceof Error ? cause.message : String(cause), details, code: null, constraint: null, table: null, kind: "unknown", cause, }); export type OperationErrors = { readonly operation: TOperation; readonly child: ( suffix: TSuffix, ) => OperationErrors<`${TOperation}.${TSuffix}`>; readonly badRequest: ( message: string, details: string, ) => ControlPlaneBadRequestError; readonly notFound: ( message: string, details: string, ) => ControlPlaneNotFoundError; readonly storage: ( error: ControlPlanePersistenceError, ) => ControlPlaneStorageError; readonly unknownPersistence: ( cause: unknown, details: string, ) => ControlPlanePersistenceError; readonly unknownStorage: ( cause: unknown, details: string, ) => ControlPlaneStorageError; readonly mapStorage: ( effect: Effect.Effect, ) => Effect.Effect; }; export type OperationErrorsLike = OperationErrors | string; export const operationErrors = ( operation: TOperation, ): OperationErrors => { const self: OperationErrors = { operation, child: (suffix) => operationErrors(`${operation}.${suffix}` as `${TOperation}.${typeof suffix}`), badRequest: (message, details) => new ControlPlaneBadRequestError({ operation, message, details, }), notFound: (message, details) => new ControlPlaneNotFoundError({ operation, message, details, }), storage: (error) => new ControlPlaneStorageError({ operation, message: error.message, details: error.details ?? "Persistence operation failed", }), unknownPersistence: (cause, details) => unknownPersistenceError(operation, cause, details), unknownStorage: (cause, details) => self.storage(self.unknownPersistence(cause, details)), mapStorage: (effect) => effect.pipe( Effect.mapError(self.storage), ), }; return self; }; export const asOperationErrors = ( errors: OperationErrorsLike, ): OperationErrors => typeof errors === "string" ? operationErrors(errors) : errors;