Skip to content

Commit a4bc07b

Browse files
committed
refactor: introduce generic error wrapping mechanism
- Add new WrappingError.swift helper with generic error wrapping functions - Refactor Auth module to use generic wrappingError(or: mapToAuthError) - Refactor Functions module to use proper error types and wrapping - Rename mapError to mapToAuthError for better clarity - Update FunctionsClient to throw FunctionsError instead of generic errors - Add comprehensive tests for new error handling in Functions module
1 parent ad08d19 commit a4bc07b

File tree

8 files changed

+186
-83
lines changed

8 files changed

+186
-83
lines changed

Sources/Auth/AuthAdmin.swift

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ public struct AuthAdmin: Sendable {
2020
/// - Parameter uid: The user's unique identifier.
2121
/// - Note: This function should only be called on a server. Never expose your `service_role` key in the browser.
2222
public func getUserById(_ uid: UUID) async throws(AuthError) -> User {
23-
try await wrappingError {
23+
try await wrappingError(or: mapToAuthError) {
2424
try await self.api.execute(
2525
self.configuration.url.appendingPathComponent("admin/users/\(uid)")
2626
)
@@ -37,7 +37,7 @@ public struct AuthAdmin: Sendable {
3737
public func updateUserById(_ uid: UUID, attributes: AdminUserAttributes) async throws(AuthError)
3838
-> User
3939
{
40-
try await wrappingError {
40+
try await wrappingError(or: mapToAuthError) {
4141
try await self.api.execute(
4242
self.configuration.url.appendingPathComponent("admin/users/\(uid)"),
4343
method: .put,
@@ -56,7 +56,7 @@ public struct AuthAdmin: Sendable {
5656
/// - Warning: Never expose your `service_role` key on the client.
5757
@discardableResult
5858
public func createUser(attributes: AdminUserAttributes) async throws(AuthError) -> User {
59-
try await wrappingError {
59+
try await wrappingError(or: mapToAuthError) {
6060
try await self.api.execute(
6161
self.configuration.url.appendingPathComponent("admin/users"),
6262
method: .post,
@@ -82,7 +82,7 @@ public struct AuthAdmin: Sendable {
8282
data: [String: AnyJSON]? = nil,
8383
redirectTo: URL? = nil
8484
) async throws(AuthError) -> User {
85-
try await wrappingError {
85+
try await wrappingError(or: mapToAuthError) {
8686
try await self.api.execute(
8787
self.configuration.url.appendingPathComponent("admin/invite"),
8888
method: .post,
@@ -107,7 +107,7 @@ public struct AuthAdmin: Sendable {
107107
///
108108
/// - Warning: Never expose your `service_role` key on the client.
109109
public func deleteUser(id: UUID, shouldSoftDelete: Bool = false) async throws(AuthError) {
110-
_ = try await wrappingError {
110+
_ = try await wrappingError(or: mapToAuthError) {
111111
try await self.api.execute(
112112
self.configuration.url.appendingPathComponent("admin/users/\(id)"),
113113
method: .delete,
@@ -129,7 +129,7 @@ public struct AuthAdmin: Sendable {
129129
let aud: String
130130
}
131131

132-
return try await wrappingError {
132+
return try await wrappingError(or: mapToAuthError) {
133133
let httpResponse = try await self.api.execute(
134134
self.configuration.url.appendingPathComponent("admin/users"),
135135
query: [

Sources/Auth/AuthClient.swift

Lines changed: 21 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -302,7 +302,7 @@ public actor AuthClient {
302302
private func _signUp(body: SignUpRequest, query: Parameters? = nil) async throws(AuthError)
303303
-> AuthResponse
304304
{
305-
let response = try await wrappingError {
305+
let response = try await wrappingError(or: mapToAuthError) {
306306
try await self.api.execute(
307307
self.configuration.url.appendingPathComponent("signup"),
308308
method: .post,
@@ -398,7 +398,7 @@ public actor AuthClient {
398398
grantType: String,
399399
credentials: Credentials
400400
) async throws(AuthError) -> Session {
401-
let session = try await wrappingError {
401+
let session = try await wrappingError(or: mapToAuthError) {
402402
try await self.api.execute(
403403
self.configuration.url.appendingPathComponent("token"),
404404
method: .post,
@@ -435,7 +435,7 @@ public actor AuthClient {
435435
) async throws(AuthError) {
436436
let (codeChallenge, codeChallengeMethod) = prepareForPKCE()
437437

438-
_ = try await wrappingError {
438+
_ = try await wrappingError(or: mapToAuthError) {
439439
try await self.api.execute(
440440
self.configuration.url.appendingPathComponent("otp"),
441441
method: .post,
@@ -474,7 +474,7 @@ public actor AuthClient {
474474
data: [String: AnyJSON]? = nil,
475475
captchaToken: String? = nil
476476
) async throws(AuthError) {
477-
_ = try await wrappingError {
477+
_ = try await wrappingError(or: mapToAuthError) {
478478
try await self.api.execute(
479479
self.configuration.url.appendingPathComponent("otp"),
480480
method: .post,
@@ -504,7 +504,7 @@ public actor AuthClient {
504504
) async throws(AuthError) -> SSOResponse {
505505
let (codeChallenge, codeChallengeMethod) = prepareForPKCE()
506506

507-
return try await wrappingError {
507+
return try await wrappingError(or: mapToAuthError) {
508508
try await self.api.execute(
509509
self.configuration.url.appendingPathComponent("sso"),
510510
method: .post,
@@ -536,7 +536,7 @@ public actor AuthClient {
536536
) async throws(AuthError) -> SSOResponse {
537537
let (codeChallenge, codeChallengeMethod) = prepareForPKCE()
538538

539-
return try await wrappingError {
539+
return try await wrappingError(or: mapToAuthError) {
540540
try await self.api.execute(
541541
self.configuration.url.appendingPathComponent("sso"),
542542
method: .post,
@@ -564,7 +564,7 @@ public actor AuthClient {
564564
)
565565
}
566566

567-
let session = try await wrappingError {
567+
let session = try await wrappingError(or: mapToAuthError) {
568568
try await self.api.execute(
569569
self.configuration.url.appendingPathComponent("token"),
570570
method: .post,
@@ -598,7 +598,7 @@ public actor AuthClient {
598598
redirectTo: URL? = nil,
599599
queryParams: [(name: String, value: String?)] = []
600600
) throws(AuthError) -> URL {
601-
try wrappingError {
601+
try wrappingError(or: mapToAuthError) {
602602
try self.getURLForProvider(
603603
url: self.configuration.url.appendingPathComponent("authorize"),
604604
provider: provider,
@@ -639,7 +639,7 @@ public actor AuthClient {
639639
let resultURL = try await launchFlow(url)
640640
return try await session(from: resultURL)
641641
} catch {
642-
throw mapError(error)
642+
throw mapToAuthError(error)
643643
}
644644
}
645645

@@ -784,7 +784,7 @@ public actor AuthClient {
784784

785785
let params = extractParams(from: url)
786786

787-
return try await wrappingError {
787+
return try await wrappingError(or: mapToAuthError) {
788788
switch self.configuration.flowType {
789789
case .implicit:
790790
guard self.isImplicitGrantFlow(params: params) else {
@@ -932,7 +932,7 @@ public actor AuthClient {
932932
}
933933

934934
do {
935-
try await wrappingError {
935+
try await wrappingError(or: mapToAuthError) {
936936
_ = try await self.api.execute(
937937
self.configuration.url.appendingPathComponent("logout"),
938938
method: .post,
@@ -1009,7 +1009,7 @@ public actor AuthClient {
10091009
query: Parameters? = nil,
10101010
body: VerifyOTPParams
10111011
) async throws(AuthError) -> AuthResponse {
1012-
let response = try await wrappingError {
1012+
let response = try await wrappingError(or: mapToAuthError) {
10131013
try await self.api.execute(
10141014
self.configuration.url.appendingPathComponent("verify"),
10151015
method: .post,
@@ -1038,7 +1038,7 @@ public actor AuthClient {
10381038
emailRedirectTo: URL? = nil,
10391039
captchaToken: String? = nil
10401040
) async throws(AuthError) {
1041-
_ = try await wrappingError {
1041+
_ = try await wrappingError(or: mapToAuthError) {
10421042
try await self.api.execute(
10431043
self.configuration.url.appendingPathComponent("resend"),
10441044
method: .post,
@@ -1068,7 +1068,7 @@ public actor AuthClient {
10681068
type: ResendMobileType,
10691069
captchaToken: String? = nil
10701070
) async throws(AuthError) -> ResendMobileResponse {
1071-
return try await wrappingError {
1071+
return try await wrappingError(or: mapToAuthError) {
10721072
try await self.api.execute(
10731073
self.configuration.url.appendingPathComponent("resend"),
10741074
method: .post,
@@ -1085,7 +1085,7 @@ public actor AuthClient {
10851085

10861086
/// Sends a re-authentication OTP to the user's email or phone number.
10871087
public func reauthenticate() async throws(AuthError) {
1088-
_ = try await wrappingError {
1088+
_ = try await wrappingError(or: mapToAuthError) {
10891089
try await self.api.execute(
10901090
self.configuration.url.appendingPathComponent("reauthenticate"),
10911091
method: .get,
@@ -1104,7 +1104,7 @@ public actor AuthClient {
11041104
///
11051105
/// Should be used only when you require the most current user data. For faster results, ``currentUser`` is recommended.
11061106
public func user(jwt: String? = nil) async throws(AuthError) -> User {
1107-
return try await wrappingError {
1107+
return try await wrappingError(or: mapToAuthError) {
11081108
if let jwt {
11091109
return try await self.api.execute(
11101110
self.configuration.url.appendingPathComponent("user"),
@@ -1139,7 +1139,7 @@ public actor AuthClient {
11391139
user.codeChallengeMethod = codeChallengeMethod
11401140
}
11411141

1142-
return try await wrappingError {
1142+
return try await wrappingError(or: mapToAuthError) {
11431143
var session = try await self.sessionManager.session()
11441144
let updatedUser = try await self.api.execute(
11451145
self.configuration.url.appendingPathComponent("user"),
@@ -1256,7 +1256,7 @@ public actor AuthClient {
12561256
redirectTo: URL? = nil,
12571257
queryParams: [(name: String, value: String?)] = []
12581258
) async throws(AuthError) -> OAuthResponse {
1259-
try await wrappingError {
1259+
try await wrappingError(or: mapToAuthError) {
12601260
let url = try self.getURLForProvider(
12611261
url: self.configuration.url.appendingPathComponent("user/identities/authorize"),
12621262
provider: provider,
@@ -1287,7 +1287,7 @@ public actor AuthClient {
12871287
/// Unlinks an identity from a user by deleting it. The user will no longer be able to sign in
12881288
/// with that identity once it's unlinked.
12891289
public func unlinkIdentity(_ identity: UserIdentity) async throws(AuthError) {
1290-
_ = try await wrappingError {
1290+
_ = try await wrappingError(or: mapToAuthError) {
12911291
try await self.api.execute(
12921292
self.configuration.url.appendingPathComponent("user/identities/\(identity.identityId)"),
12931293
method: .delete,
@@ -1308,7 +1308,7 @@ public actor AuthClient {
13081308
) async throws(AuthError) {
13091309
let (codeChallenge, codeChallengeMethod) = prepareForPKCE()
13101310

1311-
_ = try await wrappingError {
1311+
_ = try await wrappingError(or: mapToAuthError) {
13121312
try await self.api.execute(
13131313
self.configuration.url.appendingPathComponent("recover"),
13141314
method: .post,
@@ -1337,7 +1337,7 @@ public actor AuthClient {
13371337
throw AuthError.sessionMissing
13381338
}
13391339

1340-
return try await wrappingError {
1340+
return try await wrappingError(or: mapToAuthError) {
13411341
try await self.sessionManager.refreshSession(refreshToken)
13421342
}
13431343
}

Sources/Auth/AuthError.swift

Lines changed: 1 addition & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -307,30 +307,8 @@ public enum AuthError: LocalizedError {
307307
}
308308
}
309309

310-
/// Wraps an error in an ``AuthError`` if it's not already one.
311-
func wrappingError<R: Sendable>(
312-
_ block: () throws -> R
313-
) throws(AuthError) -> R {
314-
do {
315-
return try block()
316-
} catch {
317-
throw mapError(error)
318-
}
319-
}
320-
321-
/// Wraps an error in an ``AuthError`` if it's not already one.
322-
func wrappingError<R: Sendable>(
323-
@_inheritActorContext _ block: @escaping @Sendable () async throws -> R
324-
) async throws(AuthError) -> R {
325-
do {
326-
return try await block()
327-
} catch {
328-
throw mapError(error)
329-
}
330-
}
331-
332310
/// Maps an error to an ``AuthError``.
333-
func mapError(_ error: any Error) -> AuthError {
311+
func mapToAuthError(_ error: any Error) -> AuthError {
334312
if let error = error as? AuthError {
335313
return error
336314
}

Sources/Auth/AuthMFA.swift

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ public struct AuthMFA: Sendable {
2525
public func enroll(params: any MFAEnrollParamsType) async throws(AuthError)
2626
-> AuthMFAEnrollResponse
2727
{
28-
try await wrappingError {
28+
try await wrappingError(or: mapToAuthError) {
2929
try await self.api.execute(
3030
self.configuration.url.appendingPathComponent("factors"),
3131
method: .post,
@@ -46,7 +46,7 @@ public struct AuthMFA: Sendable {
4646
public func challenge(params: MFAChallengeParams) async throws(AuthError)
4747
-> AuthMFAChallengeResponse
4848
{
49-
try await wrappingError {
49+
try await wrappingError(or: mapToAuthError) {
5050
try await self.api.execute(
5151
self.configuration.url.appendingPathComponent("factors/\(params.factorId)/challenge"),
5252
method: .post,
@@ -67,7 +67,7 @@ public struct AuthMFA: Sendable {
6767
/// - Returns: An authentication response after verifying the factor.
6868
@discardableResult
6969
public func verify(params: MFAVerifyParams) async throws(AuthError) -> AuthMFAVerifyResponse {
70-
return try await wrappingError {
70+
return try await wrappingError(or: mapToAuthError) {
7171
let response = try await self.api.execute(
7272
self.configuration.url.appendingPathComponent("factors/\(params.factorId)/verify"),
7373
method: .post,
@@ -95,7 +95,7 @@ public struct AuthMFA: Sendable {
9595
@discardableResult
9696
public func unenroll(params: MFAUnenrollParams) async throws(AuthError) -> AuthMFAUnenrollResponse
9797
{
98-
try await wrappingError {
98+
try await wrappingError(or: mapToAuthError) {
9999
try await self.api.execute(
100100
self.configuration.url.appendingPathComponent("factors/\(params.factorId)"),
101101
method: .delete,
@@ -130,7 +130,7 @@ public struct AuthMFA: Sendable {
130130
///
131131
/// - Returns: An authentication response with the list of MFA factors.
132132
public func listFactors() async throws(AuthError) -> AuthMFAListFactorsResponse {
133-
try await wrappingError {
133+
try await wrappingError(or: mapToAuthError) {
134134
let user = try await sessionManager.session().user
135135
let factors = user.factors ?? []
136136
let totp = factors.filter {
@@ -150,7 +150,7 @@ public struct AuthMFA: Sendable {
150150
-> AuthMFAGetAuthenticatorAssuranceLevelResponse
151151
{
152152
do {
153-
return try await wrappingError {
153+
return try await wrappingError(or: mapToAuthError) {
154154
let session = try await sessionManager.session()
155155
let payload = JWT.decodePayload(session.accessToken)
156156

0 commit comments

Comments
 (0)