import { TaggedError } from "better-result"; export class AuthenticationError extends TaggedError("AuthenticationError")<{ statusCode: 401; message: string; }>() {} export class ApiError extends TaggedError("ApiError")<{ statusCode: number; statusText: string; code?: string; message: string; hint?: string; traceHeaders: Record; }>() {} export class MissingArgumentError extends TaggedError("MissingArgumentError")<{ field: string; message: string; }>() { constructor(args: { field: string }) { super({ field: args.field, message: `Missing required argument: ${args.field}`, }); } } export class BuildError extends TaggedError("BuildError")<{ message: string; logs?: string[]; }>() {} export class ArtifactError extends TaggedError("ArtifactError")<{ message: string; cause?: unknown; }>() {} export class TimeoutError extends TaggedError("TimeoutError")<{ versionId: string; elapsedMs: number; lastStatus: string; message: string; }>() { constructor(args: { versionId: string; elapsedMs: number; lastStatus: string; }) { super({ ...args, message: `Timed out waiting for version ${args.versionId} to reach target state (last status: ${args.lastStatus}, elapsed: ${Math.round(args.elapsedMs / 1000)}s)`, }); } } export class VersionFailedError extends TaggedError("VersionFailedError")<{ versionId: string; message: string; }>() { constructor(args: { versionId: string }) { super({ versionId: args.versionId, message: `Version ${args.versionId} transitioned to failed status`, }); } } export class NoExistingVersionError extends TaggedError( "NoExistingVersionError", )<{ serviceId: string; message: string; }>() { constructor(args: { serviceId: string }) { super({ serviceId: args.serviceId, message: `Service ${args.serviceId} has no existing versions. Environment-only updates require at least one prior deployment.`, }); } } export class NoVersionsFoundError extends TaggedError("NoVersionsFoundError")<{ serviceId: string; message: string; }>() { constructor(args: { serviceId: string }) { super({ serviceId: args.serviceId, message: `Service ${args.serviceId} has no versions`, }); } } export class CancelledError extends TaggedError("CancelledError")<{ message: string; }>() { constructor(args?: { message?: string }) { super({ message: args?.message ?? "Operation cancelled" }); } } export class DestroyAggregateError extends TaggedError( "DestroyAggregateError", )<{ message: string; succeededVersionIds: string[]; failures: Array<{ versionId: string; error: VersionOperationError }>; serviceDeleted: boolean; }>() { constructor(args: { succeededVersionIds: string[]; failures: Array<{ versionId: string; error: VersionOperationError }>; serviceDeleted: boolean; }) { const failedIds = args.failures.map((f) => f.versionId).join(", "); super({ ...args, message: `Failed to destroy ${args.failures.length} version(s): ${failedIds}`, }); } } export class InvalidOptionsError extends TaggedError("InvalidOptionsError")<{ message: string; }>() {} export class LogStreamError extends TaggedError("LogStreamError")<{ statusCode: number; message: string; }>() {} export type DeployError = | AuthenticationError | ApiError | MissingArgumentError | InvalidOptionsError | BuildError | ArtifactError | TimeoutError | VersionFailedError | CancelledError; export type UpdateEnvError = | AuthenticationError | ApiError | MissingArgumentError | InvalidOptionsError | NoExistingVersionError | TimeoutError | VersionFailedError | CancelledError; export type DestroyVersionError = | CancelledError | MissingArgumentError | NoVersionsFoundError | AuthenticationError | ApiError | TimeoutError | VersionFailedError; export type DestroyServiceError = | CancelledError | AuthenticationError | ApiError | DestroyAggregateError; export type PromoteError = | AuthenticationError | ApiError | MissingArgumentError | NoVersionsFoundError | TimeoutError | VersionFailedError | CancelledError; export type ApiRequestError = CancelledError | AuthenticationError | ApiError; export type VersionOperationError = | CancelledError | AuthenticationError | ApiError | TimeoutError | VersionFailedError;