1
1
import _Helpers
2
+ import ConcurrencyExtras
2
3
import Foundation
3
4
4
5
#if canImport(AuthenticationServices)
@@ -9,81 +10,13 @@ import Foundation
9
10
import FoundationNetworking
10
11
#endif
11
12
12
- public final class AuthClient : @unchecked Sendable {
13
- /// FetchHandler is a type alias for asynchronous network request handling.
14
- public typealias FetchHandler = @Sendable (
15
- _ request: URLRequest
16
- ) async throws -> ( Data , URLResponse )
17
-
18
- /// Configuration struct represents the client configuration.
19
- public struct Configuration : Sendable {
20
- public let url : URL
21
- public var headers : [ String : String ]
22
- public let flowType : AuthFlowType
23
- public let redirectToURL : URL ?
24
- public let localStorage : any AuthLocalStorage
25
- public let logger : ( any SupabaseLogger ) ?
26
- public let encoder : JSONEncoder
27
- public let decoder : JSONDecoder
28
- public let fetch : FetchHandler
29
-
30
- /// Initializes a AuthClient Configuration with optional parameters.
31
- ///
32
- /// - Parameters:
33
- /// - url: The base URL of the Auth server.
34
- /// - headers: Custom headers to be included in requests.
35
- /// - flowType: The authentication flow type.
36
- /// - redirectToURL: Default URL to be used for redirect on the flows that requires it.
37
- /// - localStorage: The storage mechanism for local data.
38
- /// - logger: The logger to use.
39
- /// - encoder: The JSON encoder to use for encoding requests.
40
- /// - decoder: The JSON decoder to use for decoding responses.
41
- /// - fetch: The asynchronous fetch handler for network requests.
42
- public init (
43
- url: URL ,
44
- headers: [ String : String ] = [ : ] ,
45
- flowType: AuthFlowType = Configuration . defaultFlowType,
46
- redirectToURL: URL ? = nil ,
47
- localStorage: any AuthLocalStorage ,
48
- logger: ( any SupabaseLogger ) ? = nil ,
49
- encoder: JSONEncoder = AuthClient . Configuration. jsonEncoder,
50
- decoder: JSONDecoder = AuthClient . Configuration. jsonDecoder,
51
- fetch: @escaping FetchHandler = { try await URLSession . shared. data ( for: $0) }
52
- ) {
53
- let headers = headers. merging ( Configuration . defaultHeaders) { l, _ in l }
54
-
55
- self . url = url
56
- self . headers = headers
57
- self . flowType = flowType
58
- self . redirectToURL = redirectToURL
59
- self . localStorage = localStorage
60
- self . logger = logger
61
- self . encoder = encoder
62
- self . decoder = decoder
63
- self . fetch = fetch
64
- }
65
- }
66
-
67
- @Dependency ( \. configuration)
68
- private var configuration : Configuration
69
-
70
- @Dependency ( \. api)
71
- private var api : APIClient
72
-
73
- @Dependency ( \. eventEmitter)
74
- private var eventEmitter : EventEmitter
75
-
76
- @Dependency ( \. sessionManager)
77
- private var sessionManager : SessionManager
78
-
79
- @Dependency ( \. codeVerifierStorage)
80
- private var codeVerifierStorage : CodeVerifierStorage
81
-
82
- @Dependency ( \. currentDate)
83
- private var currentDate : @Sendable ( ) -> Date
84
-
85
- @Dependency ( \. logger)
86
- private var logger : ( any SupabaseLogger ) ?
13
+ public final class AuthClient : Sendable {
14
+ private var api : APIClient { Current . api }
15
+ private var configuration : AuthClient . Configuration { Current . configuration }
16
+ private var codeVerifierStorage : CodeVerifierStorage { Current . codeVerifierStorage }
17
+ private var date : @Sendable ( ) -> Date { Current . date }
18
+ private var sessionManager : SessionManager { Current . sessionManager }
19
+ private var eventEmitter : AuthStateChangeEventEmitter { Current . eventEmitter }
87
20
88
21
/// Returns the session, refreshing it if necessary.
89
22
///
@@ -95,101 +28,22 @@ public final class AuthClient: @unchecked Sendable {
95
28
}
96
29
97
30
/// Namespace for accessing multi-factor authentication API.
98
- public let mfa : AuthMFA
99
-
31
+ public let mfa = AuthMFA ( )
100
32
/// Namespace for the GoTrue admin methods.
101
33
/// - Warning: This methods requires `service_role` key, be careful to never expose `service_role`
102
34
/// key in the client.
103
- public let admin : AuthAdmin
104
-
105
- /// Initializes a AuthClient with optional parameters.
106
- ///
107
- /// - Parameters:
108
- /// - url: The base URL of the Auth server.
109
- /// - headers: Custom headers to be included in requests.
110
- /// - flowType: The authentication flow type..
111
- /// - redirectToURL: Default URL to be used for redirect on the flows that requires it.
112
- /// - localStorage: The storage mechanism for local data..
113
- /// - logger: The logger to use.
114
- /// - encoder: The JSON encoder to use for encoding requests.
115
- /// - decoder: The JSON decoder to use for decoding responses.
116
- /// - fetch: The asynchronous fetch handler for network requests.
117
- public convenience init (
118
- url: URL ,
119
- headers: [ String : String ] = [ : ] ,
120
- flowType: AuthFlowType = AuthClient . Configuration. defaultFlowType,
121
- redirectToURL: URL ? = nil ,
122
- localStorage: any AuthLocalStorage ,
123
- logger: ( any SupabaseLogger ) ? = nil ,
124
- encoder: JSONEncoder = AuthClient . Configuration. jsonEncoder,
125
- decoder: JSONDecoder = AuthClient . Configuration. jsonDecoder,
126
- fetch: @escaping FetchHandler = { try await URLSession . shared. data ( for: $0) }
127
- ) {
128
- self . init (
129
- configuration: Configuration (
130
- url: url,
131
- headers: headers,
132
- flowType: flowType,
133
- redirectToURL: redirectToURL,
134
- localStorage: localStorage,
135
- logger: logger,
136
- encoder: encoder,
137
- decoder: decoder,
138
- fetch: fetch
139
- )
140
- )
141
- }
35
+ public let admin = AuthAdmin ( )
142
36
143
37
/// Initializes a AuthClient with a specific configuration.
144
38
///
145
39
/// - Parameters:
146
40
/// - configuration: The client configuration.
147
- public convenience init ( configuration: Configuration ) {
148
- let api = APIClient . live (
149
- configuration: configuration,
150
- http: HTTPClient (
151
- logger: configuration. logger,
152
- fetchHandler: configuration. fetch
153
- )
154
- )
155
-
156
- self . init (
157
- configuration: configuration,
158
- sessionManager: . live,
159
- codeVerifierStorage: . live,
160
- api: api,
161
- eventEmitter: . live,
162
- sessionStorage: . live,
163
- logger: configuration. logger
164
- )
165
- }
166
-
167
- /// This internal initializer is here only for easy injecting mock instances when testing.
168
- init (
169
- configuration: Configuration ,
170
- sessionManager: SessionManager ,
171
- codeVerifierStorage: CodeVerifierStorage ,
172
- api: APIClient ,
173
- eventEmitter: EventEmitter ,
174
- sessionStorage: SessionStorage ,
175
- logger: ( any SupabaseLogger ) ?
176
- ) {
177
- mfa = AuthMFA ( )
178
- admin = AuthAdmin ( )
179
-
41
+ public init ( configuration: Configuration ) {
180
42
Current = Dependencies (
181
43
configuration: configuration,
182
- sessionManager: sessionManager,
183
- api: api,
184
- eventEmitter: eventEmitter,
185
- sessionStorage: sessionStorage,
186
- sessionRefresher: SessionRefresher (
187
- refreshSession: { [ weak self] in
188
- try await self ? . refreshSession ( refreshToken: $0) ?? . empty
189
- }
190
- ) ,
191
- codeVerifierStorage: codeVerifierStorage,
192
- logger: logger
44
+ sessionRefresher: SessionRefresher { [ weak self] in
45
+ try await self ? . refreshSession ( refreshToken: $0) ?? . empty
46
+ }
193
47
)
194
48
}
195
49
@@ -204,7 +58,7 @@ public final class AuthClient: @unchecked Sendable {
204
58
public func onAuthStateChange(
205
59
_ listener: @escaping AuthStateChangeListener
206
60
) async -> some AuthStateChangeListenerRegistration {
207
- let token = eventEmitter. attachListener ( listener)
61
+ let token = eventEmitter. attach ( listener)
208
62
await emitInitialSession ( forToken: token)
209
63
return token
210
64
}
@@ -782,7 +636,7 @@ public final class AuthClient: @unchecked Sendable {
782
636
accessToken: accessToken,
783
637
tokenType: tokenType,
784
638
expiresIn: expiresIn,
785
- expiresAt: expiresAt ?? currentDate ( ) . addingTimeInterval ( expiresIn) . timeIntervalSince1970,
639
+ expiresAt: expiresAt ?? date ( ) . addingTimeInterval ( expiresIn) . timeIntervalSince1970,
786
640
refreshToken: refreshToken,
787
641
user: user
788
642
)
@@ -808,7 +662,7 @@ public final class AuthClient: @unchecked Sendable {
808
662
/// - Returns: A new valid session.
809
663
@discardableResult
810
664
public func setSession( accessToken: String , refreshToken: String ) async throws -> Session {
811
- let now = currentDate ( )
665
+ let now = date ( )
812
666
var expiresAt = now
813
667
var hasExpired = true
814
668
var session : Session
@@ -1187,7 +1041,7 @@ public final class AuthClient: @unchecked Sendable {
1187
1041
1188
1042
private func emitInitialSession( forToken token: ObservationToken ) async {
1189
1043
let session = try ? await session
1190
- eventEmitter. emit ( . initialSession, session, token)
1044
+ eventEmitter. emit ( . initialSession, session: session , token : token)
1191
1045
}
1192
1046
1193
1047
private func prepareForPKCE( ) -> ( codeChallenge: String ? , codeChallengeMethod: String ? ) {
0 commit comments