Skip to content

Commit 7086f3f

Browse files
committed
feat: add ios implementation
1 parent b35bc92 commit 7086f3f

File tree

38 files changed

+10422
-36
lines changed

38 files changed

+10422
-36
lines changed

packages/capacitor-plugin/.gitignore

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,9 @@ DerivedData/
1616
.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata
1717
.netrc
1818

19-
2019
# macOS files
2120
.DS_Store
2221

23-
24-
2522
# Based on Android gitignore template: https://github.com/github/gitignore/blob/HEAD/Android.gitignore
2623

2724
# Built application files
@@ -67,4 +64,4 @@ captures
6764
#*.jks
6865

6966
# External native build folder generated in Android Studio 2.2 and later
70-
.externalNativeBuild
67+
.externalNativeBuild

packages/capacitor-plugin/Package.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ let package = Package(
1010
targets: ["FileTransferPlugin"])
1111
],
1212
dependencies: [
13-
.package(url: "https://github.com/ionic-team/capacitor-swift-pm.git", from: "7.0.0")
13+
.package(url: "https://github.com/ionic-team/capacitor-swift-pm.git", exact: "7.1.0")
1414
],
1515
targets: [
1616
.binaryTarget(

packages/capacitor-plugin/ios/Sources/FileTransferPlugin/FileTransfer.swift

Lines changed: 0 additions & 8 deletions
This file was deleted.
Lines changed: 192 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,192 @@
1+
import Foundation
2+
import Capacitor
3+
import IONFileTransferLib
4+
5+
/// A structured error type used in file transfer operations.
6+
///
7+
/// `FileTransferError` represents various error states that can occur during file uploads and downloads,
8+
/// including validation issues, connection problems, HTTP response errors, and file system errors.
9+
struct FileTransferError: Error {
10+
11+
/// A error code in the format `OS-PLUG-FLTR-XXXX`.
12+
let code: String
13+
14+
/// A human-readable error message.
15+
let message: String
16+
17+
/// The source URL or path related to the error, if available.
18+
var source: String?
19+
20+
/// The target URL or path related to the error, if available.
21+
var target: String?
22+
23+
/// The HTTP status code, if the error is related to a network response.
24+
let httpStatus: Int?
25+
26+
/// The response body returned by the server, if any.
27+
let body: String?
28+
29+
/// The response headers returned by the server, if any.
30+
let headers: [String: String]?
31+
32+
/// The underlying error that caused this error, if any.
33+
let cause: Error?
34+
35+
/// Creates a new `FileTransferError` with the given values.
36+
///
37+
/// - Parameters:
38+
/// - code: A numeric code that will be formatted internally.
39+
/// - message: A human-readable message describing the error.
40+
/// - source: The original input source, such as a URL or path.
41+
/// - target: The intended destination, such as a URL or path.
42+
/// - httpStatus: Optional HTTP status code if error was a network response.
43+
/// - body: Optional response body.
44+
/// - headers: Optional response headers.
45+
/// - cause: Optional underlying error.
46+
init(
47+
code: Int,
48+
message: String,
49+
source: String? = nil,
50+
target: String? = nil,
51+
httpStatus: Int? = nil,
52+
body: String? = nil,
53+
headers: [String: String]? = nil,
54+
cause: Error? = nil
55+
) {
56+
self.code = String(format: "OS-PLUG-FLTR-%04d", code)
57+
self.message = message
58+
self.source = source
59+
self.target = target
60+
self.httpStatus = httpStatus
61+
self.body = body
62+
self.headers = headers
63+
self.cause = cause
64+
}
65+
66+
/// A dictionary representation of the error for use in JavaScript or other serialization contexts.
67+
///
68+
/// This includes the code, message, and optional metadata such as HTTP status,
69+
/// headers, body, and exception description.
70+
var errorInfo: JSObject {
71+
var info: JSObject = [
72+
"code": code,
73+
"message": message
74+
]
75+
if let httpStatus = httpStatus { info["httpStatus"] = httpStatus }
76+
if let body = body { info["body"] = body }
77+
if let headers = headers {
78+
let headersObj: JSObject = headers.reduce(into: [:]) { result, pair in
79+
result[pair.key] = pair.value
80+
}
81+
info["headers"] = headersObj
82+
}
83+
if let cause = cause { info["exception"] = cause.localizedDescription }
84+
85+
return info
86+
}
87+
}
88+
89+
// MARK: - Static Constructors
90+
91+
extension FileTransferError {
92+
93+
static func invalidParameters(_ message: String? = nil) -> FileTransferError {
94+
.init(code: 4, message: message ?? "The method's input parameters aren't valid.")
95+
}
96+
97+
static func invalidServerUrl(_ url: String?) -> FileTransferError {
98+
.init(
99+
code: 5,
100+
message: (url?.isEmpty ?? true)
101+
? "URL to connect to is either null or empty."
102+
: "Invalid server URL was provided - \(url!)",
103+
source: url
104+
)
105+
}
106+
107+
static func fileDoesNotExist() -> FileTransferError {
108+
.init(code: 7, message: "Operation failed because file does not exist.")
109+
}
110+
111+
static func connectionError() -> FileTransferError {
112+
.init(code: 8, message: "Failed to connect to server.")
113+
}
114+
115+
static func notModified() -> FileTransferError {
116+
.init(
117+
code: 9,
118+
message: "The server responded with HTTP 304 – Not Modified. If you want to avoid this, check your headers related to HTTP caching.",
119+
httpStatus: 304
120+
)
121+
}
122+
123+
static func httpError(
124+
responseCode: Int,
125+
message: String,
126+
responseBody: String? = nil,
127+
headers: [String: String]? = nil,
128+
cause: Error? = nil
129+
) -> FileTransferError {
130+
.init(
131+
code: 10,
132+
message: "HTTP error: \(responseCode) - \(message)",
133+
httpStatus: responseCode,
134+
body: responseBody,
135+
headers: headers,
136+
cause: cause
137+
)
138+
}
139+
140+
static func genericError(
141+
cause: Error? = nil
142+
) -> FileTransferError {
143+
.init(
144+
code: 11,
145+
message: "The operation failed with an error.",
146+
cause: cause
147+
)
148+
}
149+
}
150+
151+
// MARK: - IONFLTRException Mapping
152+
153+
extension IONFLTRException {
154+
155+
/// Converts an `IONFLTRException` to a corresponding `FileTransferError`.
156+
///
157+
/// This method maps specific cases of `IONFLTRException` to their
158+
/// equivalent `FileTransferError` cases, providing a unified error
159+
/// representation for file transfer operations.
160+
///
161+
/// - Returns: A `FileTransferError` instance representing the exception.
162+
func toFileTransferError() -> FileTransferError {
163+
switch self {
164+
case .invalidPath:
165+
return FileTransferError.invalidParameters()
166+
case .emptyURL:
167+
return FileTransferError.invalidServerUrl(nil)
168+
case .invalidURL(let url):
169+
return FileTransferError.invalidServerUrl(url)
170+
case .fileDoesNotExist:
171+
return FileTransferError.fileDoesNotExist()
172+
case .cannotCreateDirectory:
173+
return FileTransferError.genericError(cause: self)
174+
case .httpError(let responseCode, let responseBody, let headers):
175+
return responseCode == 304
176+
? FileTransferError.notModified()
177+
: FileTransferError.httpError(
178+
responseCode: responseCode,
179+
message: self.description,
180+
responseBody: responseBody,
181+
headers: headers,
182+
cause: self
183+
)
184+
case .connectionError:
185+
return FileTransferError.connectionError()
186+
case .transferError:
187+
return FileTransferError.genericError(cause: self)
188+
case .unknownError:
189+
return FileTransferError.genericError(cause: self)
190+
}
191+
}
192+
}

0 commit comments

Comments
 (0)