export type RegistrationErrorReason = | "invite_not_found" | "invite_expired" | "invite_disabled" | "invite_exhausted" | "stage_limit_reached" | "email_already_registered" | "challenge_invalid" | "challenge_expired" | "privacy_consent_required" | "privacy_notice_version_invalid" | "profile_invalid" | "idempotency_conflict" | "registration_login_required" | "login_registration_required" | "account_suspended" | "login_admin_required" | "admin_not_allowed" | "resend_too_soon" | "too_many_attempts" | "csrf_invalid" | "deletion_confirmation_invalid" | "session_invalid"; export type RegistrationErrorCode = | "REGISTRATION_REJECTED" | "REGISTRATION_REQUEST_INVALID" | "IDEMPOTENCY_KEY_CONFLICT" | "AUTH_ENTRY_REJECTED" | "AUTH_RATE_LIMITED" | "AUTH_CSRF_INVALID" | "AUTH_SESSION_INVALID"; export class RegistrationError extends Error { readonly code: RegistrationErrorCode; readonly httpStatus: 400 | 401 | 403 | 409 | 429; readonly reason: RegistrationErrorReason; constructor(code: RegistrationErrorCode, reason: RegistrationErrorReason) { super(code); this.code = code; this.httpStatus = code === "REGISTRATION_REQUEST_INVALID" ? 400 : code === "AUTH_SESSION_INVALID" ? 401 : code === "AUTH_CSRF_INVALID" ? 403 : code === "AUTH_RATE_LIMITED" ? 429 : 409; this.reason = reason; } } export function registrationFieldError(reason: RegistrationErrorReason) { const entries: Record = { challenge_expired: { field: "verification_code", message_key: "auth.challenge.expired" }, challenge_invalid: { field: "verification_code", message_key: "auth.challenge.invalid" }, email_already_registered: { field: "email", message_key: "auth.email.already_registered" }, idempotency_conflict: { field: "idempotency_key", message_key: "request.idempotency_conflict" }, invite_disabled: { field: "invite_code", message_key: "auth.invite.disabled" }, invite_exhausted: { field: "invite_code", message_key: "auth.invite.exhausted" }, invite_expired: { field: "invite_code", message_key: "auth.invite.expired" }, invite_not_found: { field: "invite_code", message_key: "auth.invite.not_found" }, privacy_consent_required: { field: "privacy_consent_accepted", message_key: "auth.privacy.consent_required" }, privacy_notice_version_invalid: { field: "privacy_notice_version", message_key: "auth.privacy.notice_version_invalid" }, profile_invalid: { field: "profile", message_key: "auth.profile.invalid" }, stage_limit_reached: { field: "invite_code", message_key: "auth.registration.stage_limit_reached" }, registration_login_required: { field: "email", message_key: "auth.registration.login_required" }, login_registration_required: { field: "email", message_key: "auth.login.registration_required" }, account_suspended: { field: "email", message_key: "auth.account.suspended" }, login_admin_required: { field: "email", message_key: "auth.login.admin_required" }, admin_not_allowed: { field: "email", message_key: "admin.auth.not_allowed" }, resend_too_soon: { field: "verification_code", message_key: "auth.challenge.resend_too_soon" }, too_many_attempts: { field: "verification_code", message_key: "auth.challenge.too_many_attempts" }, csrf_invalid: { field: "csrf_token", message_key: "auth.csrf.invalid" }, deletion_confirmation_invalid: { field: "confirmation", message_key: "account.deletion.confirmation_invalid" }, session_invalid: { field: "session", message_key: "auth.session.invalid" }, }; return entries[reason]; }