diff --git a/Sources/FirebaseAuth/FirebaseAuth+Swift.swift b/Sources/FirebaseAuth/FirebaseAuth+Swift.swift index c20658f..a196399 100644 --- a/Sources/FirebaseAuth/FirebaseAuth+Swift.swift +++ b/Sources/FirebaseAuth/FirebaseAuth+Swift.swift @@ -102,7 +102,7 @@ public final class Auth { private func fetchSignInMethodsImpl(forEmail email: String, completion: @escaping ([String]?, Error?) -> Void) { let future = swift_firebase.swift_cxx_shims.firebase.auth.auth_fetch_providers_for_email(impl, email) future.setCompletion({ - let (result, error) = future.resultAndError + let (result, error) = future.resultAndError(as: AuthErrorCode.self) var providers: [String]? if let result { providers = result.providers.map(String.init) @@ -139,7 +139,7 @@ public final class Auth { private func signInImpl(withEmail email: String, password: String, completion: @escaping (AuthDataResult?, Error?) -> Void) { let future = swift_firebase.swift_cxx_shims.firebase.auth.auth_sign_in_with_email_and_password(impl, email, password) future.setCompletion({ - let (result, error) = future.resultAndError + let (result, error) = future.resultAndError(as: AuthErrorCode.self) var data: AuthDataResult? if let result { data = .init(result) @@ -197,7 +197,7 @@ public final class Auth { private func createUserImpl(withEmail email: String, password: String, completion: @escaping (AuthDataResult?, Error?) -> Void) { let future = swift_firebase.swift_cxx_shims.firebase.auth.auth_create_user_with_email_and_password(impl, email, password) future.setCompletion({ - let (result, error) = future.resultAndError + let (result, error) = future.resultAndError(as: AuthErrorCode.self) var data: AuthDataResult? if let result { data = .init(result) @@ -250,7 +250,7 @@ public final class Auth { private func sendPasswordResetImpl(withEmail email: String, completion: @escaping (Error?) -> Void) { let future = swift_firebase.swift_cxx_shims.firebase.auth.auth_send_password_reset_email(impl, email) future.setCompletion({ - let (_, error) = future.resultAndError + let (_, error) = future.resultAndError(as: AuthErrorCode.self) completion(error) }) } diff --git a/Sources/FirebaseAuth/FirebaseAuthError.swift b/Sources/FirebaseAuth/FirebaseAuthError.swift index 6c28969..bceadab 100644 --- a/Sources/FirebaseAuth/FirebaseAuthError.swift +++ b/Sources/FirebaseAuth/FirebaseAuthError.swift @@ -1,112 +1,140 @@ // SPDX-License-Identifier: BSD-3-Clause -import Foundation +@_exported +import firebase +@_spi(FirebaseInternal) +import FirebaseCore -public enum AuthErrorCode: Int { - case invalidCustomToken = 2 - case customTokenMismatch = 3 - case invalidCredential = 4 - case userDisabled = 5 - case accountExistsWithDifferentCredential = 6 - case operationNotAllowed = 7 - case emailAlreadyInUse = 8 - case requiresRecentLogin = 9 - case credentialAlreadyInUse = 10 - case invalidEmail = 11 - case wrongPassword = 12 - case tooManyRequests = 13 - case userNotFound = 14 - case providerAlreadyLinked = 15 - case noSuchProvider = 16 - case invalidUserToken = 17 - case userTokenExpired = 18 - case networkError = 19 - case invalidAPIKey = 20 - case appNotAuthorized = 21 - case userMismatch = 22 - case weakPassword = 23 - case noSignedInUser = 24 - case apiNotAvailable = 25 - case expiredActionCode = 26 - case invalidActionCode = 27 - case invalidMessagePayload = 28 - case invalidPhoneNumber = 29 - case missingPhoneNumber = 30 - case invalidRecipientEmail = 31 - case invalidSender = 32 - case invalidVerificationCode = 33 - case invalidVerificationID = 34 - case missingVerificationCode = 35 - case missingVerificationID = 36 - case missingEmail = 37 - case missingPassword = 38 - case quotaExceeded = 39 - case retryPhoneAuth = 40 - case sessionExpired = 41 - case appNotVerified = 42 - case appVerificationUserInteractionFailure = 43 - case captchaCheckFailed = 44 - case invalidAppCredential = 45 - case missingAppCredential = 46 - case invalidClientID = 47 - case invalidContinueURI = 48 - case missingContinueURI = 49 - case keychainError = 50 - case missingAppToken = 51 - case missingIosBundleID = 52 - case notificationNotForwarded = 53 - case unauthorizedDomain = 54 - case webContextAlreadyPresented = 55 - case webContextCancelled = 56 - case dynamicLinkNotActivated = 57 - case cancelled = 58 - case invalidProviderID = 59 - case webInternalError = 60 +public struct AuthErrorCode: RawRepresentable, FirebaseError { + public typealias RawValue = Int + + public let rawValue: Int + public let localizedDescription: String + + public init(rawValue: Int) { + self.rawValue = rawValue + localizedDescription = "\(rawValue)" + } + + @_spi(FirebaseInternal) + public init(code: Int32, message: String) { + self.rawValue = Int(code) + localizedDescription = message + } + + private init(_ error: firebase.auth.AuthError) { + self.init(rawValue: Int(error.rawValue)) + } +} + +extension AuthErrorCode { + public static let none: Self = .init(firebase.auth.kAuthErrorNone) + public static let unimplemented: Self = .init(firebase.auth.kAuthErrorUnimplemented) + public static let invalidCustomToken: Self = .init(firebase.auth.kAuthErrorInvalidCustomToken) + public static let customTokenMismatch: Self = .init(firebase.auth.kAuthErrorCustomTokenMismatch) + public static let invalidCredential: Self = .init(firebase.auth.kAuthErrorInvalidCredential) + public static let userDisabled: Self = .init(firebase.auth.kAuthErrorUserDisabled) + public static let accountExistsWithDifferentCredential: Self = .init(firebase.auth.kAuthErrorAccountExistsWithDifferentCredentials) + public static let operationNotAllowed: Self = .init(firebase.auth.kAuthErrorOperationNotAllowed) + public static let emailAlreadyInUse: Self = .init(firebase.auth.kAuthErrorEmailAlreadyInUse) + public static let requiresRecentLogin: Self = .init(firebase.auth.kAuthErrorRequiresRecentLogin) + public static let credentialAlreadyInUse: Self = .init(firebase.auth.kAuthErrorCredentialAlreadyInUse) + public static let invalidEmail: Self = .init(firebase.auth.kAuthErrorInvalidEmail) + public static let wrongPassword: Self = .init(firebase.auth.kAuthErrorWrongPassword) + public static let tooManyRequests: Self = .init(firebase.auth.kAuthErrorTooManyRequests) + public static let userNotFound: Self = .init(firebase.auth.kAuthErrorUserNotFound) + public static let providerAlreadyLinked: Self = .init(firebase.auth.kAuthErrorProviderAlreadyLinked) + public static let noSuchProvider: Self = .init(firebase.auth.kAuthErrorNoSuchProvider) + public static let invalidUserToken: Self = .init(firebase.auth.kAuthErrorInvalidUserToken) + public static let userTokenExpired: Self = .init(firebase.auth.kAuthErrorUserTokenExpired) + public static let networkError: Self = .init(firebase.auth.kAuthErrorNetworkRequestFailed) + public static let invalidAPIKey: Self = .init(firebase.auth.kAuthErrorInvalidApiKey) + public static let appNotAuthorized: Self = .init(firebase.auth.kAuthErrorAppNotAuthorized) + public static let userMismatch: Self = .init(firebase.auth.kAuthErrorUserMismatch) + public static let weakPassword: Self = .init(firebase.auth.kAuthErrorWeakPassword) + public static let noSignedInUser: Self = .init(firebase.auth.kAuthErrorNoSignedInUser) + public static let apiNotAvailable: Self = .init(firebase.auth.kAuthErrorApiNotAvailable) + public static let expiredActionCode: Self = .init(firebase.auth.kAuthErrorExpiredActionCode) + public static let invalidActionCode: Self = .init(firebase.auth.kAuthErrorInvalidActionCode) + public static let invalidMessagePayload: Self = .init(firebase.auth.kAuthErrorInvalidMessagePayload) + public static let invalidPhoneNumber: Self = .init(firebase.auth.kAuthErrorInvalidPhoneNumber) + public static let missingPhoneNumber: Self = .init(firebase.auth.kAuthErrorMissingPhoneNumber) + public static let invalidRecipientEmail: Self = .init(firebase.auth.kAuthErrorInvalidRecipientEmail) + public static let invalidSender: Self = .init(firebase.auth.kAuthErrorInvalidSender) + public static let invalidVerificationCode: Self = .init(firebase.auth.kAuthErrorInvalidVerificationCode) + public static let invalidVerificationID: Self = .init(firebase.auth.kAuthErrorInvalidVerificationId) + public static let missingVerificationCode: Self = .init(firebase.auth.kAuthErrorMissingVerificationCode) + public static let missingVerificationID: Self = .init(firebase.auth.kAuthErrorMissingVerificationId) + public static let missingEmail: Self = .init(firebase.auth.kAuthErrorMissingEmail) + public static let missingPassword: Self = .init(firebase.auth.kAuthErrorMissingPassword) + public static let quotaExceeded: Self = .init(firebase.auth.kAuthErrorQuotaExceeded) + public static let retryPhoneAuth: Self = .init(firebase.auth.kAuthErrorRetryPhoneAuth) + public static let sessionExpired: Self = .init(firebase.auth.kAuthErrorSessionExpired) + public static let appNotVerified: Self = .init(firebase.auth.kAuthErrorAppNotVerified) + public static let appVerificationUserInteractionFailure: Self = .init(firebase.auth.kAuthErrorAppVerificationFailed) + public static let captchaCheckFailed: Self = .init(firebase.auth.kAuthErrorCaptchaCheckFailed) + public static let invalidAppCredential: Self = .init(firebase.auth.kAuthErrorInvalidAppCredential) + public static let missingAppCredential: Self = .init(firebase.auth.kAuthErrorMissingAppCredential) + public static let invalidClientID: Self = .init(firebase.auth.kAuthErrorInvalidClientId) + public static let invalidContinueURI: Self = .init(firebase.auth.kAuthErrorInvalidContinueUri) + public static let missingContinueURI: Self = .init(firebase.auth.kAuthErrorMissingContinueUri) + public static let keychainError: Self = .init(firebase.auth.kAuthErrorKeychainError) + public static let missingAppToken: Self = .init(firebase.auth.kAuthErrorMissingAppToken) + public static let missingIosBundleID: Self = .init(firebase.auth.kAuthErrorMissingIosBundleId) + public static let notificationNotForwarded: Self = .init(firebase.auth.kAuthErrorNotificationNotForwarded) + public static let unauthorizedDomain: Self = .init(firebase.auth.kAuthErrorUnauthorizedDomain) + public static let webContextAlreadyPresented: Self = .init(firebase.auth.kAuthErrorWebContextAlreadyPresented) + public static let webContextCancelled: Self = .init(firebase.auth.kAuthErrorWebContextCancelled) + public static let dynamicLinkNotActivated: Self = .init(firebase.auth.kAuthErrorDynamicLinkNotActivated) + public static let cancelled: Self = .init(firebase.auth.kAuthErrorCancelled) + public static let invalidProviderID: Self = .init(firebase.auth.kAuthErrorInvalidProviderId) + public static let webInternalError: Self = .init(firebase.auth.kAuthErrorWebInternalError) // There's a typo in the Firebase error, carrying it over here. - case webStorateUnsupported = 61 - case tenantIDMismatch = 62 - case unsupportedTenantOperation = 63 - case invalidDynamicLinkDomain = 64 - case rejectedCredential = 65 - case phoneNumberNotFound = 66 - case invalidTenantID = 67 - case missingClientIdentifier = 68 - case missingMultiFactorSession = 69 - case missingMultiFactorInfo = 70 - case invalidMultiFactorSession = 71 - case multiFactorInfoNotFound = 72 - case adminRestrictedOperation = 73 - case unverifiedEmail = 74 - case secondFactorAlreadyEnrolled = 75 - case maximumSecondFactorCountExceeded = 76 - case unsupportedFirstFactor = 77 - case emailChangeNeedsVerification = 78 + public static let webStorateUnsupported: Self = .init(firebase.auth.kAuthErrorWebStorateUnsupported) + public static let tenantIDMismatch: Self = .init(firebase.auth.kAuthErrorTenantIdMismatch) + public static let unsupportedTenantOperation: Self = .init(firebase.auth.kAuthErrorUnsupportedTenantOperation) + public static let invalidDynamicLinkDomain: Self = .init(firebase.auth.kAuthErrorInvalidLinkDomain) + public static let rejectedCredential: Self = .init(firebase.auth.kAuthErrorRejectedCredential) + public static let phoneNumberNotFound: Self = .init(firebase.auth.kAuthErrorPhoneNumberNotFound) + public static let invalidTenantID: Self = .init(firebase.auth.kAuthErrorInvalidTenantId) + public static let missingClientIdentifier: Self = .init(firebase.auth.kAuthErrorMissingClientIdentifier) + public static let missingMultiFactorSession: Self = .init(firebase.auth.kAuthErrorMissingMultiFactorSession) + public static let missingMultiFactorInfo: Self = .init(firebase.auth.kAuthErrorMissingMultiFactorInfo) + public static let invalidMultiFactorSession: Self = .init(firebase.auth.kAuthErrorInvalidMultiFactorSession) + public static let multiFactorInfoNotFound: Self = .init(firebase.auth.kAuthErrorMultiFactorInfoNotFound) + public static let adminRestrictedOperation: Self = .init(firebase.auth.kAuthErrorAdminRestrictedOperation) + public static let unverifiedEmail: Self = .init(firebase.auth.kAuthErrorUnverifiedEmail) + public static let secondFactorAlreadyEnrolled: Self = .init(firebase.auth.kAuthErrorSecondFactorAlreadyEnrolled) + public static let maximumSecondFactorCountExceeded: Self = .init(firebase.auth.kAuthErrorMaximumSecondFactorCountExceeded) + public static let unsupportedFirstFactor: Self = .init(firebase.auth.kAuthErrorUnsupportedFirstFactor) + public static let emailChangeNeedsVerification: Self = .init(firebase.auth.kAuthErrorEmailChangeNeedsVerification) #if INTERNAL_EXPERIMENTAL - case invalidEventHandler = 79 - case federatedProviderAlreadyInUse = 80 - case invalidAuthenticatedUserData = 81 - case federatedSignInUserInteractionFailure = 82 - case missingOrInvalidNonce = 83 - case userCancelled = 84 - case unsupportedPassthroughOperation = 85 - case tokenRefreshUnavailable = 86 + public static let invalidEventHandler: Self = .init(firebase.auth.kAuthErrorInvalidEventHandler) + public static let federatedProviderAlreadyInUse: Self = .init(firebase.auth.kAuthErrorFederatedProviderAlreadyInUse) + public static let invalidAuthenticatedUserData: Self = .init(firebase.auth.kAuthErrorInvalidAuthenticatedUserData) + public static let federatedSignInUserInteractionFailure: Self = .init(firebase.auth.kAuthErrorFederatedSignInUserInteractionFailure) + public static let missingOrInvalidNonce: Self = .init(firebase.auth.kAuthErrorMissingOrInvalidNonce) + public static let userCancelled: Self = .init(firebase.auth.kAuthErrorUserCancelled) + public static let unsupportedPassthroughOperation: Self = .init(firebase.auth.kAuthErrorUnsupportedPassthroughOperation) + public static let tokenRefreshUnavailable: Self = .init(firebase.auth.kAuthErrorTokenRefreshUnavailable) #endif // Errors that are not represented in the C++ SDK, but are // present in the reference API. - case missingAndroidPackageName = 17037 - case webNetworkRequestFailed = 17061 - case webSignInUserInteractionFailure = 17063 - case localPlayerNotAuthenticated = 17066 - case nullUser = 17067 - case gameKitNotLinked = 17076 - case secondFactorRequired = 17078 - case blockingCloudFunctionError = 17105 - case internalError = 17999 - case malformedJWT = 18000 + public static let missingAndroidPackageName: Self = .init(rawValue: 17037) + public static let webNetworkRequestFailed: Self = .init(rawValue: 17061) + public static let webSignInUserInteractionFailure: Self = .init(rawValue: 17063) + public static let localPlayerNotAuthenticated: Self = .init(rawValue: 17066) + public static let nullUser: Self = .init(rawValue: 17067) + public static let gameKitNotLinked: Self = .init(rawValue: 17076) + public static let secondFactorRequired: Self = .init(rawValue: 17078) + public static let blockingCloudFunctionError: Self = .init(rawValue: 17105) + public static let internalError: Self = .init(rawValue: 17999) + public static let malformedJWT: Self = .init(rawValue: 18000) } -extension AuthErrorCode: Error {} +extension AuthErrorCode: Equatable {} + extension AuthErrorCode { // This allows us to re-expose self as a code similarly // to what the Firebase SDK does when it creates the @@ -114,4 +142,8 @@ extension AuthErrorCode { public var code: AuthErrorCode { return self } + + public init(_ code: AuthErrorCode) { + self.init(rawValue: code.rawValue) + } } diff --git a/Sources/FirebaseAuth/FirebaseUser+Swift.swift b/Sources/FirebaseAuth/FirebaseUser+Swift.swift index 7b75d80..1102f85 100644 --- a/Sources/FirebaseAuth/FirebaseUser+Swift.swift +++ b/Sources/FirebaseAuth/FirebaseUser+Swift.swift @@ -98,7 +98,7 @@ public final class User { private func reloadImpl(completion: @escaping (Error?) -> Void) { let future = swift_firebase.swift_cxx_shims.firebase.auth.user_reload(impl) future.setCompletion({ - let (_, error) = future.resultAndError + let (_, error) = future.resultAndError(as: AuthErrorCode.self) completion(error) }) } @@ -128,7 +128,7 @@ public final class User { public func reauthenticateImpl(with credential: Credential, completion: @escaping (AuthResult?, Error?) -> Void) { let future = swift_firebase.swift_cxx_shims.firebase.auth.user_reauthenticate_and_retrieve_data(impl, credential) future.setCompletion({ - let (result, error) = future.resultAndError + let (result, error) = future.resultAndError(as: AuthErrorCode.self) completion(result, error) }) } @@ -178,7 +178,7 @@ public final class User { private func idTokenForcingRefreshImpl(_ forceRefresh: Bool, completion: @escaping (String?, Error?) -> Void) { let future = swift_firebase.swift_cxx_shims.firebase.auth.user_get_token(impl, forceRefresh) future.setCompletion({ - let (result, error) = future.resultAndError + let (result, error) = future.resultAndError(as: AuthErrorCode.self) let stringResult: String? if let result { stringResult = String(result) @@ -225,7 +225,7 @@ public final class User { public func sendEmailVerificationImpl(completion: @escaping (Error?) -> Void) { let future = swift_firebase.swift_cxx_shims.firebase.auth.user_send_email_verification(impl) future.setCompletion({ - let (_, error) = future.resultAndError + let (_, error) = future.resultAndError(as: AuthErrorCode.self) completion(error) }) } diff --git a/Sources/FirebaseCore/FirebaseError.swift b/Sources/FirebaseCore/FirebaseError.swift index 4a47c47..c93fa8a 100644 --- a/Sources/FirebaseCore/FirebaseError.swift +++ b/Sources/FirebaseCore/FirebaseError.swift @@ -1,12 +1,5 @@ // SPDX-License-Identifier: BSD-3-Clause -public struct FirebaseError: Error { - public let code: CInt - public let message: String - - @_spi(FirebaseInternal) - public init(code: CInt, message: String) { - self.code = code - self.message = message - } +public protocol FirebaseError: Error { + init(code: Int32, message: String) } diff --git a/Sources/FirebaseCore/FutureProtocol.swift b/Sources/FirebaseCore/FutureProtocol.swift index 4562662..e3b8b1f 100644 --- a/Sources/FirebaseCore/FutureProtocol.swift +++ b/Sources/FirebaseCore/FutureProtocol.swift @@ -47,10 +47,10 @@ public extension FutureProtocol { return String(cString: errorMessageUnsafe) } - var resultAndError: (ResultType?, Error?) { + func resultAndError(as errorType: ErrorType.Type) -> (ResultType?, ErrorType?) { let error = error() guard error == 0 else { - return (nil, FirebaseError(code: error, message: errorMessage!)) + return (nil, ErrorType(code: error, message: errorMessage!)) } return (result, nil) } diff --git a/Sources/FirebaseFirestore/DocumentReference+Swift.swift b/Sources/FirebaseFirestore/DocumentReference+Swift.swift index 0db1a4c..04a4299 100644 --- a/Sources/FirebaseFirestore/DocumentReference+Swift.swift +++ b/Sources/FirebaseFirestore/DocumentReference+Swift.swift @@ -31,7 +31,7 @@ extension DocumentReference { public func getDocument(source: FirestoreSource = .default, completion: @escaping (DocumentSnapshot?, Error?) -> Void) { let future = swift_firebase.swift_cxx_shims.firebase.firestore.document_get(self, source) future.setCompletion({ - let (snapshot, error) = future.resultAndError + let (snapshot, error) = future.resultAndError(as: FirestoreErrorCode.self) DispatchQueue.main.async { completion(snapshot, error) } @@ -42,7 +42,7 @@ extension DocumentReference { try await withCheckedThrowingContinuation { continuation in let future = swift_firebase.swift_cxx_shims.firebase.firestore.document_get(self, source) future.setCompletion({ - let (snapshot, error) = future.resultAndError + let (snapshot, error) = future.resultAndError(as: FirestoreErrorCode.self) if let error { continuation.resume(throwing: error) } else { @@ -99,7 +99,7 @@ extension DocumentReference { let options = merge ? firebase.firestore.SetOptions.Merge() : firebase.firestore.SetOptions() let future = swift_firebase.swift_cxx_shims.firebase.firestore.document_set_data(self, converted, options) future.setCompletion({ - let (_, error) = future.resultAndError + let (_, error) = future.resultAndError(as: FirestoreErrorCode.self) completion(error) }) } diff --git a/Sources/FirebaseFirestore/FirestoreErrorCode.swift b/Sources/FirebaseFirestore/FirestoreErrorCode.swift index fd9e4d3..ba1cd3c 100644 --- a/Sources/FirebaseFirestore/FirestoreErrorCode.swift +++ b/Sources/FirebaseFirestore/FirestoreErrorCode.swift @@ -1,14 +1,35 @@ // SPDX-License-Identifier: BSD-3-Clause -public struct FirestoreErrorCode: Error { - public typealias Code = firebase.firestore.Error +@_exported +import firebase +@_spi(FirebaseInternal) +import FirebaseCore - public let code: Code +public struct FirestoreErrorCode: RawRepresentable, FirebaseError { + public typealias RawValue = Int + + public let rawValue: Int public let localizedDescription: String + public init(rawValue: Int) { + self.rawValue = rawValue + localizedDescription = "\(rawValue)" + } + + @_spi(FirebaseInternal) + public init(code: Int32, message: String) { + self.rawValue = Int(code) + localizedDescription = message + } + + private init(_ error: firebase.firestore.Error) { + self.init(rawValue: Int(error.rawValue)) + } +} + +extension FirestoreErrorCode { init(_ error: firebase.firestore.Error, errorMessage: String?) { - code = error - localizedDescription = errorMessage ?? "\(code.rawValue)" + self.init(code: error.rawValue, message: errorMessage ?? "\(error.rawValue)") } init?(_ error: firebase.firestore.Error?, errorMessage: UnsafePointer?) { @@ -19,33 +40,40 @@ public struct FirestoreErrorCode: Error { } self.init(actualError, errorMessage: errorMessageString) } +} - public init(_ code: Code) { - self.init(code, errorMessage: nil) - } +extension FirestoreErrorCode { + public static let ok: Self = .init(firebase.firestore.kErrorOk) + public static let none: Self = .init(firebase.firestore.kErrorNone) + public static let cancelled: Self = .init(firebase.firestore.kErrorCancelled) + public static let unknown: Self = .init(firebase.firestore.kErrorUnknown) + public static let invalidArgument: Self = .init(firebase.firestore.kErrorInvalidArgument) + public static let deadlineExceeded: Self = .init(firebase.firestore.kErrorDeadlineExceeded) + public static let notFound: Self = .init(firebase.firestore.kErrorNotFound) + public static let alreadyExists: Self = .init(firebase.firestore.kErrorAlreadyExists) + public static let permissionDenied: Self = .init(firebase.firestore.kErrorPermissionDenied) + public static let resourceExhausted: Self = .init(firebase.firestore.kErrorResourceExhausted) + public static let failedPrecondition: Self = .init(firebase.firestore.kErrorFailedPrecondition) + public static let aborted: Self = .init(firebase.firestore.kErrorAborted) + public static let outOfRange: Self = .init(firebase.firestore.kErrorOutOfRange) + public static let unimplemented: Self = .init(firebase.firestore.kErrorUnimplemented) + public static let `internal`: Self = .init(firebase.firestore.kErrorInternal) + public static let unavailable: Self = .init(firebase.firestore.kErrorUnavailable) + public static let dataLoss: Self = .init(firebase.firestore.kErrorDataLoss) + public static let unauthenticated: Self = .init(firebase.firestore.kErrorUnauthenticated) } extension FirestoreErrorCode: Equatable {} -// Unfortunately `Error` is not defined as a `enum class` so we need to add -// these wrappers. -extension FirestoreErrorCode.Code { - public static var ok: Self { firebase.firestore.kErrorOk } - public static var none: Self { firebase.firestore.kErrorNone } - public static var cancelled: Self { firebase.firestore.kErrorCancelled } - public static var unknown: Self { firebase.firestore.kErrorUnknown } - public static var invalidArgument: Self { firebase.firestore.kErrorInvalidArgument } - public static var deadlineExceeded: Self { firebase.firestore.kErrorDeadlineExceeded } - public static var notFound: Self { firebase.firestore.kErrorNotFound } - public static var alreadyExists: Self { firebase.firestore.kErrorAlreadyExists } - public static var permissionDenied: Self { firebase.firestore.kErrorPermissionDenied } - public static var resourceExhausted: Self { firebase.firestore.kErrorResourceExhausted } - public static var failedPrecondition: Self { firebase.firestore.kErrorFailedPrecondition } - public static var aborted: Self { firebase.firestore.kErrorAborted } - public static var outOfRange: Self { firebase.firestore.kErrorOutOfRange } - public static var unimplemented: Self { firebase.firestore.kErrorUnimplemented } - public static var `internal`: Self { firebase.firestore.kErrorInternal } - public static var unavailable: Self { firebase.firestore.kErrorUnavailable } - public static var dataLoss: Self { firebase.firestore.kErrorDataLoss } - public static var unauthenticated: Self { firebase.firestore.kErrorUnauthenticated } +extension FirestoreErrorCode { + // This allows us to re-expose self as a code similarly + // to what the Firebase SDK does when it creates the + // underlying NSErrors on iOS/macOS. + public var code: FirestoreErrorCode { + return self + } + + public init(_ code: FirestoreErrorCode) { + self.init(rawValue: code.rawValue) + } } diff --git a/Sources/FirebaseFirestore/Query+Swift.swift b/Sources/FirebaseFirestore/Query+Swift.swift index cac438a..ddd1ee5 100644 --- a/Sources/FirebaseFirestore/Query+Swift.swift +++ b/Sources/FirebaseFirestore/Query+Swift.swift @@ -32,7 +32,7 @@ extension QueryProtocol { public func getDocuments(source: FirestoreSource = .default, completion: @escaping (QuerySnapshot?, Error?) -> Void) { let future = swift_firebase.swift_cxx_shims.firebase.firestore.query_get(_asQuery, source) future.setCompletion({ - let (snapshot, error) = future.resultAndError + let (snapshot, error) = future.resultAndError(as: FirestoreErrorCode.self) DispatchQueue.main.async { completion(snapshot, error) } @@ -43,7 +43,7 @@ extension QueryProtocol { try await withCheckedThrowingContinuation { continuation in let future = swift_firebase.swift_cxx_shims.firebase.firestore.query_get(_asQuery, source) future.setCompletion({ - let (snapshot, error) = future.resultAndError + let (snapshot, error) = future.resultAndError(as: FirestoreErrorCode.self) if let error { continuation.resume(throwing: error) } else { diff --git a/Sources/FirebaseFirestore/WriteBatch+Swift.swift b/Sources/FirebaseFirestore/WriteBatch+Swift.swift index 4f43379..5dccc5b 100644 --- a/Sources/FirebaseFirestore/WriteBatch+Swift.swift +++ b/Sources/FirebaseFirestore/WriteBatch+Swift.swift @@ -44,7 +44,7 @@ extension WriteBatch { public mutating func commit(completion: @escaping ((Error?) -> Void) = { _ in }) { let future = swift_firebase.swift_cxx_shims.firebase.firestore.write_batch_commit(self) future.setCompletion({ - let (_, error) = future.resultAndError + let (_, error) = future.resultAndError(as: FirestoreErrorCode.self) DispatchQueue.main.async { completion(error) } @@ -55,7 +55,7 @@ extension WriteBatch { try await withCheckedThrowingContinuation { (continuation: CheckedContinuation) in let future = swift_firebase.swift_cxx_shims.firebase.firestore.write_batch_commit(self) future.setCompletion({ - let (_, error) = future.resultAndError + let (_, error) = future.resultAndError(as: FirestoreErrorCode.self) if let error { continuation.resume(throwing: error) } else {