@@ -17,21 +17,20 @@ import AppKit.NSImage
17
17
#endif
18
18
19
19
@available ( iOS 15 . 0 , macOS 12 . 0 , tvOS 15 . 0 , watchOS 8 . 0 , * )
20
- public final class OpenAIDefaultLoader : IOpenAILoader {
20
+ public final class OpenAIDefaultLoader : IOpenAILoader {
21
21
22
22
/// HTTP async client to handle requests
23
- private let client : Http . Proxy < JsonReader , JsonWriter > ?
23
+ private let client : Http . Proxy < JsonReader , JsonWriter > ?
24
24
25
25
/// Endpoint parameters required for making requests
26
- private let endpoint : IOpenAIImageEndpoint
26
+ private let endpoint : IOpenAIImageEndpoint
27
27
28
28
/// Initializes the loader with endpoint parameters
29
29
/// - Parameter endpoint: Set of parameters for making requests
30
- public init ( endpoint : IOpenAIImageEndpoint ) {
31
-
30
+ public init ( endpoint: IOpenAIImageEndpoint ) {
32
31
self . endpoint = endpoint
33
32
34
- guard let url = URL ( string: endpoint. urlString) else {
33
+ guard let url = URL ( string: endpoint. urlString) else {
35
34
client = nil
36
35
return
37
36
}
@@ -45,33 +44,52 @@ public final class OpenAIDefaultLoader : IOpenAILoader{
45
44
/// - size: The size of the generated image
46
45
/// - Returns: OpenAI Image
47
46
public func load(
48
- _ prompt : String ,
49
- with size : OpenAIImageSize
50
- ) async throws -> Image {
51
-
52
- // Prepare the request body with the prompt and size
53
- let body = Input ( prompt: prompt, size: size, response_format: . b64, n: 1 )
54
-
55
- // Set the request headers, including authorization
56
- let headers = [ " Content-Type " : " application/json " , " Authorization " : " Bearer \( endpoint. apiKey) " ]
57
- let path = endpoint. path
47
+ _ prompt: String ,
48
+ with size: OpenAIImageSize
49
+ ) async throws -> Image {
58
50
59
- guard let client = client else {
51
+ guard let client = client else {
60
52
throw AsyncImageErrors . clientIsNotDefined
61
53
}
62
54
63
- // Send the request and get the response
64
- let result : Http . Response < Output > = try await client. post ( path: path, body: body, headers: headers)
55
+ do {
56
+ let ( path, body, headers) = prepareRequest ( prompt: prompt, size: size)
57
+ let result : Http . Response < Output > = try await client. post ( path: path, body: body, headers: headers)
58
+ return try imageBase64 ( from: result. value)
59
+
60
+ } catch {
61
+ try handleRequestError ( error)
62
+ }
63
+ }
64
+
65
+ /// Prepares the request with the necessary parameters
66
+ /// - Parameters:
67
+ /// - prompt: The text prompt describing the desired image
68
+ /// - size: The size of the generated image
69
+ /// - Returns: A tuple containing the path, body, and headers for the request
70
+ private func prepareRequest( prompt: String , size: OpenAIImageSize ) -> ( String , Input , [ String : String ] ) {
71
+ let body = Input ( prompt: prompt, size: size, response_format: . b64, n: 1 )
72
+ let headers = [ " Content-Type " : " application/json " , " Authorization " : " Bearer \( endpoint. apiKey) " ]
73
+ let path = endpoint. path
74
+ return ( path, body, headers)
75
+ }
76
+
77
+ /// Handles errors that occur during the request
78
+ /// - Parameter error: The error that occurred
79
+ private func handleRequestError( _ error: Error ) throws -> Never {
80
+ if case let Http . Errors . status( _, _, data) = error, let responseData = data {
81
+ let data = String ( data: responseData, encoding: . utf8) ?? " Unable to decode data "
82
+ throw AsyncImageErrors . httpStatus ( data)
83
+ }
65
84
66
- // Convert the response to an image
67
- return try imageBase64 ( from: result. value)
85
+ throw error
68
86
}
69
87
70
88
/// Decodes base64 encoded string to Data
71
89
/// - Parameter output: The output received from the endpoint
72
90
/// - Returns: Decoded Data
73
- private func decodeBase64( from output: Output ) throws -> Data ? {
74
- guard let base64 = output. firstImage else {
91
+ private func decodeBase64( from output: Output ) throws -> Data ? {
92
+ guard let base64 = output. firstImage else {
75
93
throw AsyncImageErrors . returnedNoImages
76
94
}
77
95
@@ -83,10 +101,9 @@ public final class OpenAIDefaultLoader : IOpenAILoader{
83
101
/// - Parameter output: OpenAI response type
84
102
/// - Returns: UIImage
85
103
private func imageBase64( from output: Output ) throws -> Image {
86
-
87
104
let data = try decodeBase64 ( from: output)
88
105
89
- if let data, let image = UIImage ( data: data) {
106
+ if let data, let image = UIImage ( data: data) {
90
107
return Image ( uiImage: image)
91
108
}
92
109
@@ -99,10 +116,9 @@ public final class OpenAIDefaultLoader : IOpenAILoader{
99
116
/// - Parameter output: OpenAI response type
100
117
/// - Returns: NSImage
101
118
private func imageBase64( from output: Output ) throws -> Image {
102
-
103
119
let data = try decodeBase64 ( from: output)
104
120
105
- if let data, let image = NSImage ( data: data) {
121
+ if let data, let image = NSImage ( data: data) {
106
122
return Image ( nsImage: image)
107
123
}
108
124
0 commit comments